1994 1995 1996 1997 1998 1999 2000 2001 2002 <2003> 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 | Index | 1994 1995 1996 1997 1998 1999 2000 2001 2002 <2003> 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 |
<== Date ==> | <== Thread ==> |
---|
Subject: | Long expressions using MAX and MIN in CALC fields |
From: | "Redman, Russell O." <[email protected]> |
To: | "Tech-Talk (E-mail)" <[email protected]> |
Date: | Tue, 25 Feb 2003 15:57:11 -0800 |
I would like to suggest a small enhancement for the calcRecord,
calcoutRecord and waitRecord code that uses the postfix routine. This
enhancement will allow the MAX and MIN operators to be used on many more
input fields than is currently possible due to the limited number of
characters permitted in the CALC fields of these records.
My motivation for this change is that I would like to use a SINGLE calcout
record to evaluate
MIN(2,MAX(A,B,C,D,E,F,G,H,I))
i.e. the MAX of nine input fields with an upper limit of 2. The calcout
record has trouble with this because the MAX(X,Y) function has only two
arguments. The shortest expression I can come up with to evaluate this is
MIN(2,MAX(MAX(MAX(MAX(A,B),MAX(C,D)),MAX(MAX(E,F),MAX(G,H))),I))
which is difficult to read and contains 64 characters, far more than the 36
characters permitted. I know I can do the calculation with a select record
and a calcout, but these records are used in a time sensitive part of my
database and the calculation is nested quite deeply. If at all possible, I
would like to complete the operation using a single calcout record.
I would like to suggest a change in the expression syntax for the MIN and
MAX functions to allow these kinds of long expressions. Currently, the
expression
MAX(A,B)
generates RPCL
FETCH_A
FETCH_B
MAX
In an ideal world, I would like the MIN and MAX operators to accept a
variable number of arguments, so that an expression like
MAX(A,B,C,D)
might generate RPCL of the form
FETCH_A
FETCH_B
FETCH_C
FETCH_D
MAX
MAX
MAX
However, I do not understand the postfix subroutine well enough to see how
to do this.
A much easier approach to implement is to treat MAX and MIN as binary
operators. In the existing postfix.c code MAX and MIN are handled as UNARY
operators, but mathematically they can equally well be considered to be
binary operators that are commutative and associative, similar in many ways
to the '+' and '*' operators. With an infix notation, we could write my
expression as
2 min (A max B max C max D max E max F max G max H max I).
This is fairly easy to understand but does not save enough characters and
might be difficult to distinguish from the MAX and MIN functions in existing
databases . Unfortunately, most of the obvious punctuation characters have
already been used for other operations, but I suggest that "|<" and ">|"
might be suitable as binary MIN and MAX operators, respectively. I do not
believe that these combinations would ever occur in a valid expression in an
existing database. My expression would then become
2|<(A>|B>|C>|D>|E>|F>|G>|H>|I).
This is more cryptic, but contains only 30 characters and is simple to
implement. In the postfix.c code, insert the two lines
{">|", 7, 8, BINARY_OPERATOR, MAX}, /* maximum of 2 args
*/
{"|<", 7, 8, BINARY_OPERATOR, MIN}, /* minimum of 2 args
*/
in the table of operators immediately after the MAX and MIN entries. This
is the only required code change. It is then necessary to rebuild libCom
and iocCore, to touch rec/calcRecord.c, rec/calcoutRecord.c and waitRecord.c
and rebuild rec, and (for me at least) to rebuild my record support.
With this simple change, the assignment
-> dbpf "simb:b.CALC","(A>|B>|C)|<D"
gives
RPCL: 0x010203434304447f094343434343434343484000
which I interpret as
0x01 = FETCH_A
0x02 = FETCH_B
0x03 = FETCH_C
0x43 = MAX
0x43 = MAX
0x04 = FETCH_D
0x44 = MIN
0x7f = END_STACK
(Ignore the garbage after the END_STACK token.)
With this simple change it is possible to take the MAX or MIN of every input
field in a calcRecord or a calcoutRecord, as well as more complex
expressions such as the one I was after.
In sCalcPostfix.c there is code for an alternative implementation of the
postfix operation. This generates different tokens in the RPCL field and is
not used for the calcRecord or calcoutRecord in R3.13.5. I have made the
corresponding changes in sCalcPostfix.c to the table of operators, but have
not been able to test them. I have attached both postfix.c and
sCalcPostfix.c to this message.
Dr. Russell O. Redman
Tel: (250) 363-6917 | Fax: (250) 363-0045
<mailto:[email protected]>
National Research Council Canada | Conseil national de recherches Canada
5071 West Saanich Road | 5071 West Saanich Road
Victoria, B. C. V9E 2E7 | Victoria, C.-B. V9E 2E7
Government of Canada | Gouvernement du Canada
Attachment:
postfix.c
Description: Binary data
Attachment:
sCalcPostfix.c
Description: Binary data