TABLE OF CONTENTS
MathString.mcc/MathString.mcc
MathString.mcc/MUIA_MathString_Behaviour
MathString.mcc/MUIA_MathString_Constants
MathString.mcc/MUIA_MathString_DefaultUnit
MathString.mcc/MUIA_MathString_Functions
MathString.mcc/MUIA_MathString_LastError
MathString.mcc/MUIA_MathString_Units
MathString.mcc/MUIA_MathString_Value
MathString.mcc/MUIA_MathString_ValueFormat
MathString.mcc/MUIA_MathString_ValueMode
MathString.mcc/MUIA_MathString_ValueUnit
MathString.mcc/MUIM_MathString_Eval
MathString.mcc/MUIM_MathString_FuncEval
MathString.mcc/MathString.mcc MathString.mcc/MathString.mcc
MathString is a subclass of the String class that adds mathematical
abilities to its superclass.
A MathString object can accept complex floating-point expressions,
including algebraic operators, functions, measuring units, and
return to the application only the value of the expression, giving
the user the freedom to express a value as (S)HE feels it's easier,
without burdening the application. For most things, handling
a MathString object is as easy as a traditional String object via
the MUIA_String_Integer tag.
The language accepted by a MathString object is as follows:
id ::= 1-to-4-character (like IFF's IDs)
num ::= signed floating point, simple or exponential notation
mnum ::= num | num id /* id is measuring unit */
mexp ::= mnum | mexp*mnum | mexp/mnum | (aexp)
| id(aexp) /* id is function name */
| id /* id is a constant */
aexp ::= mexp | aexp+mexp | aexp-mexp
Spaces are not significant, except between digits, in an id, or
between an id and a "(".
Some example:
3.4 m / (1e10+3Km)
2*sin(30°)
1 in - 12 pt
cos(pi)/(1/3)
MathString supports custom measuring units, custom functions,
custom constants, single- or double-precision IEEE and FFP modes,
automatic error handling, several built-in measuring systems
and more.
NOTES
MathString needs the mathieeedoubtrans.library & mathtrans.library.
BUGS
GO TO CONTENTS
MathString.mcc/MUIA_MathString_Behaviour
MUIA_MathString_Behaviour -- (V1) [.SG], ULONG
You can fine tune some behavioural aspects of a MathString object
by using this attribute. The parameter you supply must be a bit
mask of the actions you want, ORed together. When you want to
change only some of the behaviour bit, please GET the current
MUIA_MathString_Behaviour, use logical ORs / ANDs to set or
clear the bits you are interested in, and SET back the result.
This way, you will retain compatibility with future MathString
enhancement. Think of this when tempted to use this attribute
at object creation time, then don't use it.
Also, don't touch MUIA_MathString_Behaviour unless you have a
very good reason to modify it; users expect a MathString object
to behave consistently between multiple applications, and may be
very upset by any strangeness (e.g.: uncommon error handling).
INPUTS
These are the values you can put in your bit mask.
When an error is found in the input string:
MSB_ONERROR_BEEP Call DisplayBeep()
MSB_ONERROR_ACTIVATE Activate the string gadget
MSB_ONERROR_SPOT Place the string gadget's cursor on error
When a MUIM_MathString_Eval happens:
MSB_ONEVAL_SUBST Put the result back in the string gadget
When the user acknowledges the input (i.e., by pressing RETURN)
MSB_ONACKNOWLEDGE_EVAL Call MUIM_MathString_Eval
When the application GETs MUIA_MathString_Value:
MSB_ONGETVALUE_EVAL Call MUIM_MathString_Eval
More flags could be defined in the future.
The (current) default behaviour is:
MSB_ONERROR_BEEP | MSB_ONERROR_ACTIVATE | MSB_ONERROR_SPOT |
MSB_ONEVAL_SUBST | MSB_ONACKNOWLEDGE_EVAL
EXAMPLE
Suppose you want to disable the DisplayBeep() on errors:
ULONG behaviour;
get(obj,MUIA_MathString_Behaviour,&behaviour);
behaviour &= (~MSB_ONERROR_BEEP);
set(obj,MUIA_MathString_Behaviour,behaviour);
NOTES
BUGS
SEE ALSO
MUIA_MathString_LastError
MUIA_MathString_Value
MUIA_MathString_Value
MUIA_MathString_Value
GO TO CONTENTS
MathString.mcc/MUIA_MathString_Constants
MUIA_MathString_Constants -- (V1) [ISG], struct constdef *
You can supply your own constants to a MathString object by
filling an array of constdef's, so defined in MathString_mcc.h:
struct constdef {
ULONG id; right-justified constant, eg <\0,\0,\0,e>
double value; in double-precision IEEE format
};
The array MUST be terminated by a NULL entry:
{NULL, 0.0}
As you can see, the constants's IDs are expressed as a 4-character
constant (this method is the same used in the IFF standard); you
can easily obtain the right value for a given string by using
some language's multi-character constants (eg, 'pi' in C, "pi" in E)
or by using the standard macro MAKE_ID (eg, MAKE_ID(0,0,'p','i')).
The value MUST be expressed as a double-precision IEEE number
(64 bit); use the relevant functions from the system's math libraries
if your language/environment doesn't support this kind of notation.
The scale used for constants' value is the same used in the units's
factor, i.e. values are "absolute".
MUIA_MathString_Constants defaults to NULL, meaning that no constant
is accepted.
NOTES
The constdef array is not copied, and should stay valid for the
entire lifetime of the object.
Constants names are case-sensitive.
EXAMPLE
Some (useful?) constant:
struct constdef my_const[] = {
'one', 1.0,
'two', 2.0,
'pi', 3.14159265358979323846,
NULL, 0.0
};
set(obj,MUIA_MathString_Constants,&my_const);
BUGS
SEE ALSO
MUIA_MathString_Eval
MUIA_MathString_Units
MUIA_MathString_Units
GO TO CONTENTS
MathString.mcc/MUIA_MathString_DefaultUnit
MUIA_MathString_DefaultUnit -- (V1) [ISG], LONG
You can choose which of the units in your measuring system is to
be considered the "default" one. Every number entered by the user
without a specific unit ID following it, will be considered as
expressed in this defaul unit; moreover, all the calculations will
be performed in this unit (this could affect the amount of roundoff
error introduced by the calculation, but since double precision IEEE
is used, you can probably forget about it).
The number you specify here is taken as an INDEX in the units table,
0 being the first unit (and the default).
BUGS
SEE ALSO
MUIA_MathString_Units
MUIA_MathString_ValueUnit
MUIA_MathString_ValueUnit
GO TO CONTENTS
MathString.mcc/MUIA_MathString_Functions
MUIA_MathString_Functions -- (V1) [ISG], struct fundef *
You can supply a set of functions that the user can call in the
expression entered into the string gadget. These functions are
installed via a NULL-terminated array of struct fundef, so defined
in MathString_mcc.h:
struct fundef {
ULONG id; right-justified constant, eg <\0,a,b,s>
struct Hook funh; hook to be called
};
The function ID can be built via multi-character constants or by
the IFF-standard MAKE_ID() macro, in the same way as for the units.
Your hook function will be called with a pointer to the Hook in A0,
a pointer to the MUI object in A2 and a pointer to a double-precision
IEEE number (your argument) in A1.
You should put the result in the double pointed to by A1, and return
(in D0) an error code, MS_OK indicating that the function call was
successfull.
Any other value will be regarded as an error and put, as usual, in
MUIA_MathString_LastError.
Nothing prevents you from using other MS_ constants aswell, but
it is better to define your own error codes; values 256-4095 of
MUIA_MathString_LastError are reserved for this purpose.
This attribute defaults to NULL, meaning that no custom function is
implemented.
EXAMPLE
SAVEDS ASM ULONG absf( REG(a0) struct Hook *h,
REG(a1) double *arg,
REG(a2) Object *obj)
{
*arg = (*arg>=0.0)?*arg:-(*arg); /* absolute value */
return 0;
}
SAVEDS ASM ULONG sqrf( REG(a0) struct Hook *h,
REG(a1) double *arg,
REG(a2) Object *obj)
{
if (*arg<0.0)
return 260; /* custom error code */
*arg = sqrt(*arg); /* square root */
return 0;
}
struct fundef myfun[] = {
MAKE_ID( 0 ,'a','b','s'), {{0,0},absf,0,0},
MAKE_ID('s','q','r','t'), {{0,0},sqrf,0,0},
NULL };
set(obj,MUIA_MathString_Functions,myfun);
NOTES
The fundef array is not copied and should stay valid for the
entire lifetime of the object.
No support is available for multi-argument functions. No support
is available for symbolic computation, either. Use Maple V.
Functions names are case-sensitive.
BUGS
SEE ALSO
MUIA_MathString_Units
MUIM_MathString_Eval
GO TO CONTENTS
MathString.mcc/MUIA_MathString_LastError
MUIA_MathString_LastError -- (V1) [.SG], ULONG
This attribute contains the error code from the last evaluation.
Altough you can set this one yourself, you should never need to do it:
MUIA_MathString_LastError is reset to MS_OK every time an evaluation
occurs, and set to a specific error code if the input string is not a
correct expression.
Note that the default handling for errors is to call DisplayBeep(),
keeping the string gadget active and placing the cursor the the exact
spot of the error; this behaviour should be acceptable in most cases
(you can change it via MUIA_MathString_Behaviour, but please don't
do this without a good reason).
When you get MUIA_MathString_Value after an evaluation, remember to
check for MUIA_MathString_LastError being MS_OK!
RESULT
MS_OK no error
MS_WRONG_NUMBER syntax error while parsing a number
MS_WRONG_FUNCALL syntax error in function call
MS_MISSING_CLOSE_PAREN missing a ")"
MS_SYNTAX_ERROR general syntax error
MS_WRONG_UNIT wrong unit name, or unknown unit
MS_DIVIDE_BY_ZERO division by zero
MS_WRONG_CONSTANT wrong constant name, on unknown constant
Custom functions, installed via MUIA_MathString_Functions, could
return other error codes; values in the range 256-4095 are reserved
for this purpose.
NOTES
Setting MUIA_MathString_LastError to MS_OK does NOT trigger a
notification; if you ask for a notification on this attribute,
you will only hear about true errors.
More error codes could be added in future releases; if you receive
an error code you don't know, handle it in a sensible manner
(i.e., "Unknown error %d"): you can't just use error code as an
index into an array.
BUGS
SEE ALSO
MUIA_MathString_Eval
MUIA_MathString_Functions
MUIA_MathString_Units
MUIA_MathString_Units
MUIA_MathString_Units
GO TO CONTENTS
MathString.mcc/MUIA_MathString_Units MathString.mcc/MUIA_MathString_Units
MUIA_MathString_Units -- (V1) [ISG], struct umdef *
A MathString object can accept several measuring units in its input.
In the input string, an "unit ID" can follow a floating-point number
and acts as a multiplier, returning the number's value multiplied by
the unit's own "factor".
You can define a measuring system by filling an array of umdef's, so
defined in MathString_mcc.h:
struct umdef {
ULONG id; right-justified constant, eg <\0,\0,c,m>
double factor; in double-precision IEEE format
};
The array MUST be terminated by a NULL entry:
{NULL, 0.0}
As you can see, the unit's IDs are expressed as a 4-character
constant (this method is the same used in the IFF standard); you
can easily obtain the right value for a given string by using
some language's multi-character constants (eg, 'cm' in C, "cm" in E)
or by using the standard macro MAKE_ID (eg, MAKE_ID(0,0,'c','m')).
The factor MUST be expressed as a double-precision IEEE number
(64 bit); use the relevant functions from the system's math libraries
if your language/environment doesn't support this kind of notation.
Usually, your preferred unit gets a factor of 1.0, so that the
"absolute" value of the expression is measured in your preferred
unit, but this in absolutely not required. You could, for example,
set up your units in such a way that the "absolute" value is expressed
in 300-dpi pixels, while the user can only chose between centimetres
(cm) and inches (in) -- see example.
MUIA_MathString_Units defaults to NULL, meaning that no unit is
accepted - only dealing with absolute numbers.
SPECIAL INPUTS
Several measuring systems are already built-in, so you can specify
some special value for MUIA_MathString_Units:
MUIV_MathString_Units_Metric -- metric system
mm millimetres 1
cm centimetres 10
dm decimetres 100
m metres 1000
dam dacametres 10000
hm hettometres 100000
km kilometres 1000000
MUIV_MathString_Units_Typo -- typographical sizes
pt pica points 1
pi picas 12
mm millimetres 72/2.54/10
cm centimetres 72/2.54
in inches 72
c ciceros 72/2.54*2.2163
d didot points 72/2.54*2.2163/12
MUIV_MathString_Units_CS -- computer science's sizes
b bytes 1
nib nibbles 0.5
kb kilobytes 1024
Mb megabytes 1024^2
Gb gigabytes 1024^3
Tb terabytes 1024^4
MUIV_MathString_Units_Angular
° degrees PI/180
rad radians 1.0
deg centesimal degrees (militar) PI/200
MUIV_MathString_Units_Time
ns nanoseconds 1/1000000000
µs microseconds 1/1000000
ms milliseconds 1/1000
s seconds 1
m minutes 60
h hours 60*60
d days 24*60*60
week week 7*24*60*60 (7 days)
yr year 365*24*60*60 (365 days)
ayr astr. year 365.256*24*60*60 (365.256 days)
EXAMPLE
A standard case, absolute values are in Hz:
struct umdef freq[] = {
'Hz', 1.0,
'KHz', 1000.0,
'MHz', 1000000.0,
NULL, 0.0 };
set(obj,MUIA_MathString_Units,&freq);
An uncommon case, absolute values are 300-dpi pixels:
struct umdef dpiunit[] = {
'in', 300.0,
'cm', 300.0/2.54,
NULL, 0.0 };
NOTES
The umdef array is not copied, and should stay valid for the
entire lifetime of the object.
At this stage, MathString doesn't support offsetted units, like
temperature ones (°C / °F / °K); you can use a "conversion" custom
function to work around this limitation. In case you feel that
a more general scheme would indeed be useful, let me know.
Units names are case-sensitive.
BUGS
SEE ALSO
MUIA_MathString_Eval
MUIA_MathString_DefUnit
nit
nit
GO TO CONTENTS
MathString.mcc/MUIA_MathString_Value MathString.mcc/MUIA_MathString_Value
MUIA_MathString_Value -- (V1) [ISG], LONG
This attributes gets or sets the value in the string gadget.
The argument you pass could be an FFP number, a single-precision
IEEE number or a pointer to a double-precision IEEE number, depending
on the (current) setting of MUIA_MathString_ValueMode; in any case,
the value could be expressed in absolute terms or in the (current)
default unit, depending on the (current) setting of the attribute
MUIA_MathString_ValueUnit.
Please note that the value returned is only valid if there was no
error (MUIA_MathString_LastError = MS_OK); otherwise, the value
obtained comes from "skipping over" the error.
Setting this attribute causes the value to be shown in the string
gadget as per MUIA_MathString_ValueFormat.
Getting this attribute can cause an automatic evaluation, if so
requested via MUIA_MathString_Behaviour.
EXAMPLE
See MUIA_MathString_ValueMode.
NOTES
Usually, you can have two models in your interaction with a MathString
object. In the first, call it user-driven, the user asynchronously
plays with the gadget contents; you place a notification on
MUIA_MathString_Value and GET its value when receiving a notification.
This is the most common case, and the default MUIA_MathString_Behaviour
handles this quite well.
On the contrary, in the second model (call it application-driven),
you are interested in reading the value only when some other
event occurs (e.g., when the user "commits" via an "OK" or "Save"
button). In this case, you could disable MSB_ONACKNOWLEDGE_EVAL
and ask instead for MSB_ONGETVALUE_EVAL in MUIA_MathString_Behaviour,
or maybe manually call MUIM_MathString_Eval before GETting the value,
and you should not need any notification on MUIA_MathString_Value.
In any case, try to figure what behaviour could be more "natural"
to the user: the first model is adequate in almost any situation,
and has the added benefit of immediately giving feedback to the
user if the expression entered contains any error.
Also, if your application does some kind of "approximation" on the
value, put back the result with a SET of MUIA_MathString_Value, so
that the user always sees the same value the application does.
In the same vein, always use a MUIA_MathString_ValueFormat that
rounds the result in the same way your application does. Again,
always maintain the consistency between the "internal" value
used by your application and what the user sees in the gadget.
BUGS
SEE ALSO
MUIM_MathString_Eval
MUIA_MathString_ValueFormat
ode
MUIA_MathString_ValueUnit
GO TO CONTENTS
MathString.mcc/MUIA_MathString_ValueFormat
MUIA_MathString_ValueFormat -- (V1) [ISG], STRPTR
When an evaluation takes place, the resulting value is put back
in the string gadget's buffer. You can specify a printf-like format
you wish applied to the value. You have two arguments available:
a double-precision value and an unit ID; the default format is thus
a mere "%g %s".
EXAMPLE
set(obj,MUIA_MathString_ValueFormat,"%.3f %s");
NOTES
You should try to use a format that produces a string that is a
valid expression itself, so the user can easily re-evaluate it
or use the current value as part of a more complex expression.
So, while you could swap the unit and the value (ie, "%s %f"), the
resulting string would not be accepted by a future evaluation,
and the user would have to re-type the value itself everytime.
Try hard to maintain consistency between the value put back in
the string gadget and the value as known to your application,
e.g. performing the same rounding in both the format string and
on the value you got.
BUGS
SEE ALSO
MUIA_MathString_Behaviour
GO TO CONTENTS
MathString.mcc/MUIA_MathString_ValueMode
MUIA_MathString_ValueMode -- (V1) [ISG], LONG
MathString supports three different "modes" of floating-point
support; the best one for your application depends on the level
of accuracy you need and on the kind of support your language or
environment offers you on the floating-point ground.
The evaluation of the expression is always performed internally
using double-precision IEEE routines, so the accuracy loss in only
relative to the final rounding while offering you the result.
INPUTS
MUIV_MathString_ValueMode_dIEEEptr:
The value you get from MUIA_MathString_Value is a pointer
to a double-precisione IEEE number (64 bit) - default.
MUIV_MathString_ValueMode_sIEEE:
The value you get from MUIA_MathString_Value is a single
precision IEEE number (32 bit).
MUIV_MathString_ValueMode_sFFP:
The value you get from MUIA_MathString_Value is a single
precision FFP number (32 bit).
EXAMPLE
Assuming your compiler is set-up for double or mixed IEEE math:
double value;
double *pd;
set(obj, MUIA_MathString_ValueMode, MUIV_MathString_ValueMode_dIEEEptr);
get(obj, MUIA_MathString_Value, &pd);
value = *pd;
NOTES
Some language or compiler doesn't offer you much choice. While the
SAS/C, for example, supports both FFP and (double or single) IEEE,
the v2.1 Amiga E compiler only supported FFP, and later releases
only support single precision IEEE.
Be carefull - setting the wrong mode could lead to bad errors.
BUGS
SEE ALSO
MUIA_MathString_ValueUnit
MUIA_MathString_Value
MUIA_MathString_Value
GO TO CONTENTS
MathString.mcc/MUIA_MathString_ValueUnit
MUIA_MathString_ValueUnit -- (V1) [ISG], LONG
You can ask for the value of an expression to be reported either in
absolute terms (that is the default) or in the (current) default unit.
INPUTS
MUIV_MathString_ValueUnit_Absolute - returns absolute value
MUIV_MathString_ValueUnit_DefUnit - use default unit
NOTES
Next version could add the capability to ask for any of your units.
BUGS
SEE ALSO
MUIA_MathString_Value
MUIA_MathString_ValueMode
MUIA_MathString_ValueMode
GO TO CONTENTS
MathString.mcc/MUIM_MathString_Eval MathString.mcc/MUIM_MathString_Eval
MUIM_MathString_Eval -- (V1)
SYNOPSIS
DoMethod(obj,MUIM_MathString_Eval)
This method cause the evaluation of the object's MUIA_String_Contents;
the result is stored internally and can be retrieved by getting the
MUIA_MathString_Value attribute. A textual representation of the result
is put back in the gadget, as per MUIA_MathString_ValueFormat,
unless disabled via MUIA_MathString_Behaviour.
This method is also automatically executed whenever the user
acknowledges the input (ie., by pressing RETURN in the gadget),
unless disabled via MUIA_MathString_Behaviour (again);
in many cases, you can just set up a notification on
MUIA_MathString_Value and forget about all the rest.
After an evaluation, MUIA_MathString_LastError is set to MS_OK if
there was no error, or to a specific error code otherwise.
NOTES
The representation of the result is affected by
MUIA_MathString_ValueMode and MUIA_MathString_ValueUnit; be sure
these attributes are set in a way that matches your language's
(or compiler's) floating point support.
If an evaluation doesn't change the value of the result, you will
not get any notification on MUIA_MathString_Value. Besides being
a good thing in itself, this prevents endless loops when you
put a notification on MUIA_MathString_Value and ask for an
automatic MUIM_MathString_Eval when GETting MUIA_MathString_Value
(i.e., you get notified of a change in _Value and GET it, thus
triggering and _Eval that changes the _Value and so on...).
BUGS
SEE ALSO
MUIA_MathString_Value
MUIA_MathString_ValueMode
it
MUIA_MathString_ValueFormat
MUIA_MathString_Behaviour
MUIA_MathString_Behaviour
GO TO CONTENTS
MathString.mcc/MUIM_MathString_FuncEval
MUIM_MathString_FuncEval -- (V1)
SYNOPSIS
Never call, for subclasses implementors only.
When a MathString object needs to evaluate a custom
function, it sends itself a MUIM_MathString_FuncEval method
with the following parameters:
ULONG MethodID; always MUIM_MathString_FuncEval
ULONG id; right-justified constant, eg <\0,a,b,s>
double *arg; in double-precision IEEE format
... private fields follow
The default handling for this method is to search the
MUIA_MathString_Functions list for an hook matching the given id
and calling the relevant user function; subclass writers could
prefer redefining MUIM_MathString_FuncEval instead (this way,
the subclass could be subclassed itself while adding new
functions at every level).
Please be sure to pass any unrecognized id to the superclass!
This method must return an error code, MS_OK meaning no error;
the result of the function call must be placed in *arg.
NOTES
You could easily define specialized MathStrings, i.e.
FinancialMathString, NuclearPhysicMathString and so on.
What about making such classes public?
If, on the other hand, you are not writing a subclass,
using hooks (MUIA_MathString_Functions) should be somewhat
easier.
BUGS
To make MathString really fully customizable for subclasses,
one would also need methods for units, constants and string
conversion (stringify). It is not anticipated that such strong
customization will be needed in real cases; if you are doing a
second-order subclassing of MathString that would require
such methods, please write to the author.
EXAMPLE
Our custom MUIM_MathString_FuncEval knows of a function
six(x) always returning 6x.
ULONG myMathString_FuncEval(struct IClass *cl,Object *obj,
struct MUIP_MathString_FuncEval *msg)
{
if (msg->id == 'six') {
*(msg->arg) = 6.0 * (msg->arg);
return 0;
}
else
return DoSuperMethodA(cl,obj,msg);
}
The dispatcher: our subclass only differs from MathString
in the six() function.
SAVEDS ASM ULONG SMclass_Dispatcher(REG(a0) struct IClass *cl,
REG(a2) Object *obj, REG(a1) Msg msg)
{
switch (msg->MethodID) {
case MUIM_MathString_FuncEval:
return (myMathString_FuncEval(cl,obj,
(struct MUIP_MathString_FuncEval *)msg));
default:
return DoSuperMethodA(cl,obj,msg);
}
}
SEE ALSO
MUIA_MathString_Functions