Discussion:
[ast-developers] [patch] 2nd ${var.CONST} test patch... / was: Re: float i; (( i.MAX, i.MIN, i.EPSILON )) constants?
Roland Mainz
2013-08-26 21:15:50 UTC
Permalink
cc: ast-developers at lists.research.att.com
Subject: Re: Re: [ast-developers] float i; (( i.MAX, i.MIN, i.EPSILON )) constants?
--------
Erm... doesn't this just require a small modification of the
arithmetic engine (I don't know how to do the same for a plain
${i.MAX}), e.g. do a type-based (technically we "only" have six types
- three integer and three float) lookup of the matching constant value
if an integer name is followed by a '.' ?
First of all there are 9 types, 3 float, 3 integer, and 3 unsigned.
Secondly, it is much simpler of i.MAX only appears in arithmetic
expressions and cannot be used as ${i.MAX} because ${i.MAX} is
more complex because it needs to work with ${i.MAX op string}
and ${op i.MAX} as well.
I am not even sure how to implement ${!i.M*} given the current
architecture.
Maybe I should restrict b.true to arithmetic expressions only.
Programs that want ${i.MAX} can do $((i.MAX)).
Anyway, I have enough bug reports to keep me busy for now.
Attached (as "astksh20130814_math_constants001.diff.txt") is a
[snip]
2. The implementation is inconsistant in that ${!foo*} does not
expand all integer variables starting with foo to each of the
18 integer or 27 possible float suffices for integer and float
respectively.
Is it hard to fix this?
Yes and no. Implementing ${!x.M*} is "easy" but with the limitation
that it will return the name of the variable containing the value and
not something under the x.* naming hieracy.
This isn't technically bad since it basically returns the static
properly of the class (or type) and therefore should return a name
under the class/type hieracy (for example java does it in a similar
way, e.g. |Double x; x.getClass.MIN_EXPONENT|) and not a name under
the variable itself.

I've attached a new patch as "astksh20130814_math_constants002.diff.txt" ...

Example usage:
-- snip --
$ ksh -o nounset -c 'compound .mathconst=( compound _binary80=(float
MYVAL=nan M_PI=3.1415) _binary64=( float MYVAL=inf M_PI=3.14 )) ;
typeset -lE x=5.5 ; print "${!x.*}" ; true'
.mathconst._binary80.MYVAL .mathconst._binary80.M_PI

$ ksh -o nounset -c 'compound .mathconst=( compound _binary80=(float
MYVAL=nan M_PI=3.1415) _binary64=( float MYVAL=inf M_PI=3.14 )) ;
typeset -E x=5.5 ; print "${!x.*}" ; true'
.mathconst._binary64.MYVAL .mathconst._binary64.M_PI
-- snip --

* Notes:
- I changed the naming scheme a bit and also renamed ".sh.mathconst"
to ".mathconst" because a compound variable under ".sh" has somehow
trouble with ${!var*} constructs... and I'm a bit lazy tonight and
didn't want to dig around to squish this bug

- I'm now using the IEEE764-2008 names of the floating-point values.
Maybe someday we make typeset -E/-F/-G/-X an alias to _Binary64 and
add _Binary32/_Binary@(80|128) and later Binary16 (half float) plus
_Decimal@(32|64|128). That would require a minor reorg of the
arithmetric code, e.g. replacing the Sfdouble_t with a per-type
variable and add a per-type function lookup table (similar to how C++
does this stuff). The advantage would be that we can just plug-in more
types with little or no effort, get much better performance because we
have much less casting between floating-point and integer types and
far less |if() ... else ...| in the code (at the expense of having
more indirections) and can handle integers with maximum values greater
than the largest floating-point type can reliably accept (e.g. larger
than |LDBL_MAX_10_EXP|), e.g. an |int128_t|'s maximum value can't be
converted into a |long double| and back... you loose some digits in
that process...).

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -r -u original/src/cmd/ksh93/include/defs.h build_numconstants/src/cmd/ksh93/include/defs.h
--- src/cmd/ksh93/include/defs.h 2013-08-12 16:31:56.000000000 +0200
+++ src/cmd/ksh93/include/defs.h 2013-08-26 20:30:55.380701728 +0200
@@ -423,6 +423,8 @@
extern char *sh_mactrim(Shell_t*,char*,int);
extern int sh_macexpand(Shell_t*,struct argnod*,struct argnod**,int);
extern bool sh_macfun(Shell_t*,const char*,int);
+extern const char *sh_get_arith_constant_prefix(Shell_t *, Namval_t *);
+Namval_t *sh_get_arith_constant(Shell_t *, char *);
extern void sh_machere(Shell_t*,Sfio_t*, Sfio_t*, char*);
extern void *sh_macopen(Shell_t*);
extern char *sh_macpat(Shell_t*,struct argnod*,int);
diff -r -u original/src/cmd/ksh93/sh/arith.c build_numconstants/src/cmd/ksh93/sh/arith.c
--- src/cmd/ksh93/sh/arith.c 2013-08-12 16:43:47.000000000 +0200
+++ src/cmd/ksh93/sh/arith.c 2013-08-26 21:53:30.109673997 +0200
@@ -59,6 +59,98 @@
"?",
};

+const char *sh_get_arith_constant_prefix(Shell_t *shp, Namval_t *np)
+{
+ const char *prefix = NULL;
+
+ if(nv_isattr(np, NV_INTEGER))
+ {
+ /*
+ * See http://en.wikipedia.org/wiki/IEEE_floating_point#Basic_formats
+ * for the basic IEEE 764-2008 |_binary*| names
+ */
+ if((LDBL_MANT_DIG > 64) && (nv_isattr(np, NV_LDOUBLE) == NV_LDOUBLE))
+ {
+ prefix = "_binary128";
+ }
+ else if((LDBL_MANT_DIG == 64) && (nv_isattr(np, NV_LDOUBLE) == NV_LDOUBLE))
+ {
+ prefix = "_binary80";
+ }
+ else if((LDBL_MANT_DIG < 64) && (nv_isattr(np, NV_LDOUBLE) == NV_LDOUBLE))
+ {
+ prefix = "_binary64";
+ }
+ else if(nv_isattr(np, NV_FLOAT) == NV_FLOAT)
+ {
+ prefix = "_binary32";
+ }
+ else if(nv_isattr(np, NV_DOUBLE) == NV_DOUBLE)
+ {
+ prefix = "_binary64";
+ }
+ else if(nv_isattr(np, NV_UINT64) == NV_UINT64)
+ {
+ prefix = "uint64_t";
+ }
+ else if(nv_isattr(np, NV_UINT16) == NV_UINT16)
+ {
+ prefix = "uint16_t";
+ }
+ else if(nv_isattr(np, NV_UNT32) == NV_UNT32)
+ {
+ prefix = "uint32_t";
+ }
+ else if(nv_isattr(np, NV_INT64) == NV_INT64)
+ {
+ prefix = "int64_t";
+ }
+ else if(nv_isattr(np, NV_INT16) == NV_INT16)
+ {
+ prefix = "int16_t";
+ }
+ else if(nv_isattr(np, NV_INT32) == NV_INT32)
+ {
+ prefix = "int32_t";
+ }
+ }
+
+ return prefix;
+}
+
+Namval_t *sh_get_arith_constant(Shell_t *shp, char *cp)
+{
+ Namval_t *np;
+ char *ld;
+ char saved_ld;
+ const char *prefix;
+
+ ld = strrchr(cp, '.');
+ if (!ld)
+ return (0);
+ saved_ld = *ld;
+ *ld = '\0';
+ np = nv_open(cp, shp->var_tree, NV_VARNAME|NV_NOADD|NV_NOFAIL);
+ *ld = saved_ld;
+ if (!np)
+ return (NULL);
+ prefix = sh_get_arith_constant_prefix(shp, np);
+ nv_close(np);
+
+ if (prefix)
+ {
+ char buff[256];
+ sprintf(buff, ".mathconst.%s.%s", prefix, ld+1);
+ np = nv_open(buff, shp->var_tree ,NV_VARNAME|NV_NOADD|NV_NOFAIL);
+ }
+ else
+ {
+ np = NULL;
+ }
+
+ return (np);
+}
+
static Namval_t *scope(register Namval_t *np,register struct lval *lvalue,int assign)
{
register int flag = lvalue->flag;
@@ -90,8 +182,14 @@
cp[flag] = d;
return(&FunNode);
}
- if(!np && assign)
- np = nv_open(cp,shp->var_tree,assign|NV_VARNAME);
+ if (!np)
+ {
+ if (assign)
+ np = nv_open(cp,shp->var_tree,assign|NV_VARNAME);
+ else
+ np = sh_get_arith_constant(shp, cp);
+ }
+
cp[flag] = d;
if(!np)
return(0);
diff -r -u original/src/cmd/ksh93/sh/macro.c build_numconstants/src/cmd/ksh93/sh/macro.c
--- src/cmd/ksh93/sh/macro.c 2013-07-31 22:08:40.000000000 +0200
+++ src/cmd/ksh93/sh/macro.c 2013-08-26 20:53:37.804249920 +0200
@@ -1083,12 +1083,43 @@
return(count);
}

-static char *nextname(Mac_t *mp,const char *prefix, int len)
+static char *nextname(Mac_t *mp, char *prefix, int len)
{
char *cp;
if(len==0)
{
- mp->nvwalk = nv_diropen((Namval_t*)0,prefix,mp->shp);
+
+#if 1
+ Namval_t *np;
+ char *ld;
+ char saved_ld;
+ const char *acp = NULL;
+
+ mp->nvwalk = NULL;
+
+ ld = strrchr(prefix, '.');
+ if (ld)
+ {
+ saved_ld = *ld;
+ *ld = '\0';
+ np = nv_open(prefix, mp->shp->var_tree, NV_VARNAME|NV_NOADD|NV_NOFAIL);
+ if (np)
+ {
+ acp = sh_get_arith_constant_prefix(mp->shp, np);
+ if (acp)
+ {
+ char buff[256];
+ sprintf(buff, ".mathconst.%s.%s", acp, ld+1);
+ mp->nvwalk = nv_diropen((Namval_t*)0, buff, mp->shp);
+ }
+ nv_close(np);
+ }
+ *ld = saved_ld;
+ }
+
+ if (!acp && !mp->nvwalk)
+ mp->nvwalk = nv_diropen((Namval_t*)0,prefix,mp->shp);
+#endif
return((char*)mp->nvwalk);
}
if(!(cp=nv_dirnext(mp->nvwalk)))
@@ -1349,6 +1380,11 @@
fcmbget(&LEN);
return(true);
}
+
+ if(!np && (flag&NV_NOADD))
+ {
+ np = sh_get_arith_constant(mp->shp, id);
+ }
}
if(np && (flag&NV_NOADD) && nv_isnull(np))
{
Loading...