[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Axiom-developer] Re: [Frink] Units
[Axiom-developer] Re: [Frink] Units
Thu, 29 Sep 2005 03:30:06 -0600
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.7) Gecko/20050414
Tim Daly wrote:
> On the Axiom mailing list we have been discussing this particular topic.
> Axiom is a free, general purpose computer algebra system similar in
> scope and power to Mathematica and Maple. It does not currently support
> Units or Dimensions on input values but this is being discussed.
> (see http://page.axiom-developer.org)
> I see that the software is "free" but I couldn't find the source
> anywhere. I was hoping to learn what you've already done so I could
> have a better reference point than my own, uneducated opinion. Is
> the source available for study?
I'll post my initial response to both of the lists you referenced in
the original mail, as Frink users might be interested in how units are
implemented in Frink. Follow-ups should probably be directed to one
list or another, or to me personally.
The source for Frink is currently not available, but I think it's
more useful to talk about the high-level design decisions rather than
particulars of implementation, which may change.
As you know, there are lots of different ways that units and
dimensions could be implemented, and a lot of tradeoffs in performance,
memory usage, complexity, reversibility, and flexibility. I've seen
As noted in your mailing lists, I described the implementation
somewhat in my talk at the Lightweight Languages 4 conference at MIT.
The slides and video are available at:
Some design goals are:
* Avoid hard-coding of any units of measure or dimensions. The
number and base dimensions should be specified at run-time by a
configurable units file.
* Try to make all operations constant-time.
* Allow adding of base dimensions at runtime. This is, in practice,
very rare and often ill-advised, (in fact, I've *never* had to do it,)
but may be a useful construct in some cases.
* Allow for a variety of implementations. In Java, this translates
to defining everything as an interface, and keeping each interface as
simple as possible.
* It makes absolutely no difference what your internal representation
or base dimensions are. That's just a display-time issue. The user
should either 1.) ask for results in specific units (which provides an
important check that dimensions are what they expect) 2.) Set default
display units, see http://futureboy.us/frinkdocs/#SettingDisplayUnits
3.) define their own unit file with the dimensions they like to use, or
4.) accept what comes out.
* Don't try to solve the case of non-linear units within your system.
Fahrenheit, Celsius, decibel, stellar magnitude, etc., are examples of
non-linear units with nonsensical zero points. Frink implements these
as functions which require the user to understand the difference between
these units and ordinary linear units. Doing anything else requires
reading minds, which is destined to fail.
There are lots of ways that units could be implemented. My
implementation can be described succinctly. Every unit is a combination
of a magnitude (as a multiple of some base dimensions) and a list of
dimensions and their exponents.
The decision to immediately reduce all values to multiples of some
base dimensions was chosen for performance and simplicity of coding. It
has the disadvantage of going through a potential longer chain of
multiplications than if you kept the relations in a graph. If these
multiplications are irreversible, like with most floating-point
implementations, this can cause problems or precision loss. Frink tries
to avoid this by maintaining exact rational numbers when possible.
(e.g. an inch is defined as exactly 254/100 cm.)
The standard data file uses SI base units as the base dimensions.
This is, of course, configurable at run-time:
The Unit interface:
The DimensionList interface:
The DimensionList interface tends to imply that you have an array of
integers which represent exponents. This was done for simplicity and
performance, but it could be implemented alternately with a linked list
and a more complex enumerator and data structure returned, but this
would likely be slower. This interface has one minor optimization in
it. The getHighestIndex() method returns the highest index *used* for
that particular DimensionList, allowing quicker array operations,
especially if the most-used dimensions were defined first. It also
allows you to add dimensions at runtime with no penalty.
A class called DimensionManager keeps track of all of the base
dimensions (defined by a simplistic interface called Dimension) and
their names, base units, and index numbers. As a concession to
efficiency, each fundamental dimension has an index associated with it.
The first dimension added has a number of 0, and this increases by one
for each dimension added. This number is guaranteed not to change over
the course of a run, but may change across runs.
To allow implementations of some of these interfaces to be as minimal
as possible, without deriving from another class, math on Units and
DimensionLists are performed by other classes which use the methods
defined by these interfaces to perform all necessary operations.
I know that this is a rather terse discussion, but hopefully it will
be helpful. My primary recommendation is to not make your
implementation more complex than need be. Implementing units really can
be quite simple. Please let me know if you have more specific questions.
* JSR-108, a Java Community Process proposal for implementing Units
in Java. This was withdrawn by the leader in 2004. In my opinion, it's
overly complex and hard-coded. http://jsr-108.sourceforge.net/
Alan Eliasen | "It's amazing how much mature wisdom
address@hidden | resembles being too tired."
http://futureboy.homeip.net/ | -- Robert Heinlein