I am writing a library to handle quantities with units (e.g. metres, etc).
Originally, units were described as SI units plus a numeric scale factor. However, this excluded annoying units like Celsius, which are shifted instead of (or as well as) scaled.
Thus I decided to represent a unit by a function to map the SI unit to the new unit. Users could use lambdas (the library uses C++0x) to easily describe simple scales and translations, while also theoretically being able to come up with whatever crazy units they want with more complex functions.
However, it is necessary to go both from the custom unit to SI and back. Thus an inverse function is needed. Previously, one would just reciprocate the scale factor, but obviously it's more complicated now. Is there some generic way I can numerically invert a given function f:R->R (i.e. long double f(long double))? If not, do I have any option other than to have the user provide the function and its inverse.
Thanks,
-Xander
EDIT: It occurs to me that I should probably somehow impose that the functions be monotonic (not that I can think how to effectively do that...), then it would be possible to (inefficiently) compute an inverse by trial and improvement.
I would limit myself to affine transformations, and maybe throw in a log somewhere. Can you think of any phenomenon that is measured with one function in one unit and with a totally different function in another?
Okay, yeah some functions aren't invertible. I would like to impose the monotonicity (either all increasing or all decreasing) of functions used - otherwise the units will be badly defined anyway.
Now, any monotonic function does have an inverse, I think. I considered y=ax+b at first, but due to the existence of funny (logarithmic?) scaled units such as dB, I hoped to keep things general.
I can possibly invert an arbitrary monotonic function, though with poor efficiency. So the new question is how can I impose monotonicity (at runtime) in an efficient way?
@helios Well the Richter scale and pH are also logarithmic IIRC, though I'm not sure where the Richter scale comes in anyway, with regard to mass/length/time/current/temperature/amount of substance/luminous intensity. However, the library is supposed to allow custom units and who I am to tell the end user he can't measure in exp(sin^2) metres ;)
@Duoas It looks like it will be a lot of hurt, but I thought it might be a bad idea to trust the user to invert his/her own function. Perhaps I could let the user enter both, but throw an exception if the f(f^-1(x)) != x for a range of values of x?
Well the Richter scale and pH are also logarithmic IIRC
I have no idea how Richter values are calculated, but I don't think they're convertible to any other unit.
pH is an affine transformation with a decimal logarithm wedged in.
You could do it like this: have the user enter a, b, c, and base, and the conversion function is automatically defined:
If c==0: ax + b
If c==1: a logbase x + b
If c==2: logbase ax + b
If c==3: logbase(ax + b)
EDIT: You can have negative values turn the logarithm into an exponentiation, too, or the other way around.