
Hi all. The attached diff makes some changes to Numexpr support for booleans. The changes and their rationale are below. 1. New ``True`` and ``False`` boolean constants. This is so that 1 and 0 are always proper integer constants. It is also for completeness, but I don't envision any usage for them that couldn't be expressed without the constants. 2. The only comparisons supported with booleans are ``==`` and ``!=``, so that you can compare boolean variables. Just as NumPy supports complex order comparisons and Numexpr doesn't, so goes for bools. Being relatively new, I think there is no need to keep integer-boolean compatibility in Numexpr. What was the meaning of ``True > False`` or ``2 > True`` anyway? 3. This is also why casting booleans to normal numbers is not allowed, so ``prod()`` and ``sum()`` on booleans aren't either. What is the meaning of boolean addition anyway? To make it short, this patch is kind of a strengthening of boolean values. I expect some people to disagree with the changes, and that's why I would really like to hear your opinions on it. Regards, :: Ivan Vilata i Balaguer >qo< http://www.carabos.com/ Cárabos Coop. V. V V Enjoy Data "" ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Numpy-discussion mailing list Numpy-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/numpy-discussion

Ivan Vilata i Balaguer wrote:
Hi all. The attached diff makes some changes to Numexpr support for booleans. The changes and their rationale are below.
1. New ``True`` and ``False`` boolean constants. This is so that 1 and 0 are always proper integer constants. It is also for completeness, but I don't envision any usage for them that couldn't be expressed without the constants.
I'm puzzled. Python already has constants True and False of the bool type. bool is a subclass of the int type. Any instance of the bool type can be converted to the int type.
a=1==0 type(a) <type 'bool'> int(a) 0 a False
Colin W.
2. The only comparisons supported with booleans are ``==`` and ``!=``, so that you can compare boolean variables. Just as NumPy supports complex order comparisons and Numexpr doesn't, so goes for bools. Being relatively new, I think there is no need to keep integer-boolean compatibility in Numexpr. What was the meaning of ``True > False`` or ``2 > True`` anyway?
3. This is also why casting booleans to normal numbers is not allowed, so ``prod()`` and ``sum()`` on booleans aren't either. What is the meaning of boolean addition anyway?
To make it short, this patch is kind of a strengthening of boolean values. I expect some people to disagree with the changes, and that's why I would really like to hear your opinions on it.
Regards,
::
Ivan Vilata i Balaguer >qo< http://www.carabos.com/ Cárabos Coop. V. V V Enjoy Data ""
------------------------------------------------------------------------
Index: interp_body.c =================================================================== --- interp_body.c (revisión: 2299) +++ interp_body.c (copia de trabajo) @@ -130,21 +130,22 @@ ci_dest = c1i);
case OP_INVERT_BB: VEC_ARG1(b_dest = !b1); + case OP_AND_BBB: VEC_ARG2(b_dest = (b1 && b2)); + case OP_OR_BBB: VEC_ARG2(b_dest = (b1 || b2));
- case OP_AND_BBB: VEC_ARG2(b_dest = b1 && b2); - case OP_OR_BBB: VEC_ARG2(b_dest = b1 || b2); + case OP_EQ_BBB: VEC_ARG2(b_dest = (b1 == b2)); + case OP_NE_BBB: VEC_ARG2(b_dest = (b1 != b2));
- case OP_GT_BII: VEC_ARG2(b_dest = (i1 > i2) ? 1 : 0); - case OP_GE_BII: VEC_ARG2(b_dest = (i1 >= i2) ? 1 : 0); - case OP_EQ_BII: VEC_ARG2(b_dest = (i1 == i2) ? 1 : 0); - case OP_NE_BII: VEC_ARG2(b_dest = (i1 != i2) ? 1 : 0); + case OP_GT_BII: VEC_ARG2(b_dest = (i1 > i2)); + case OP_GE_BII: VEC_ARG2(b_dest = (i1 >= i2)); + case OP_EQ_BII: VEC_ARG2(b_dest = (i1 == i2)); + case OP_NE_BII: VEC_ARG2(b_dest = (i1 != i2));
- case OP_GT_BFF: VEC_ARG2(b_dest = (f1 > f2) ? 1 : 0); - case OP_GE_BFF: VEC_ARG2(b_dest = (f1 >= f2) ? 1 : 0); - case OP_EQ_BFF: VEC_ARG2(b_dest = (f1 == f2) ? 1 : 0); - case OP_NE_BFF: VEC_ARG2(b_dest = (f1 != f2) ? 1 : 0); + case OP_GT_BFF: VEC_ARG2(b_dest = (f1 > f2)); + case OP_GE_BFF: VEC_ARG2(b_dest = (f1 >= f2)); + case OP_EQ_BFF: VEC_ARG2(b_dest = (f1 == f2)); + case OP_NE_BFF: VEC_ARG2(b_dest = (f1 != f2));
- case OP_CAST_IB: VEC_ARG1(i_dest = (long)b1); case OP_ONES_LIKE_II: VEC_ARG1(i_dest = 1); case OP_NEG_II: VEC_ARG1(i_dest = -i1);
@@ -157,7 +158,6 @@
case OP_WHERE_IFII: VEC_ARG3(i_dest = f1 ? i2 : i3);
- case OP_CAST_FB: VEC_ARG1(f_dest = (long)b1); case OP_CAST_FI: VEC_ARG1(f_dest = (double)(i1)); case OP_ONES_LIKE_FF: VEC_ARG1(f_dest = 1.0); case OP_NEG_FF: VEC_ARG1(f_dest = -f1); @@ -180,8 +180,6 @@ case OP_FUNC_FF: VEC_ARG1(f_dest = functions_f[arg2](f1)); case OP_FUNC_FFF: VEC_ARG2(f_dest = functions_ff[arg3](f1, f2));
- case OP_CAST_CB: VEC_ARG1(cr_dest = (double)b1; - ci_dest = 0); case OP_CAST_CI: VEC_ARG1(cr_dest = (double)(i1); ci_dest = 0); case OP_CAST_CF: VEC_ARG1(cr_dest = f1; @@ -203,8 +201,8 @@ ci_dest = (c1i*c2r - c1r*c2i) / fa; cr_dest = fb);
- case OP_EQ_BCC: VEC_ARG2(b_dest = (c1r == c2r && c1i == c2i) ? 1 : 0); - case OP_NE_BCC: VEC_ARG2(b_dest = (c1r != c2r || c1i != c2i) ? 1 : 0); + case OP_EQ_BCC: VEC_ARG2(b_dest = (c1r == c2r && c1i == c2i)); + case OP_NE_BCC: VEC_ARG2(b_dest = (c1r != c2r || c1i != c2i));
case OP_WHERE_CFCC: VEC_ARG3(cr_dest = f1 ? c2r : c3r; ci_dest = f1 ? c2i : c3i); Index: compiler.py =================================================================== --- compiler.py (revisión: 2299) +++ compiler.py (copia de trabajo) @@ -217,6 +217,10 @@ for name in c.co_names: if name == "None": names[name] = None + elif name == "True": + names[name] = True + elif name == "False": + names[name] = False else: t = types.get(name, float) names[name] = expr.VariableNode(name, type_to_kind[t]) Index: tests/test_numexpr.py =================================================================== --- tests/test_numexpr.py (revisión: 2299) +++ tests/test_numexpr.py (copia de trabajo) @@ -67,10 +67,6 @@ x = x + 5j assert_equal(evaluate("sum(x**2+2,axis=0)"), sum(x**2+2,axis=0)) assert_equal(evaluate("prod(x**2+2,axis=0)"), prod(x**2+2,axis=0)) - # Check boolean (should cast to integer) - x = (arange(10) % 2).astype(bool) - assert_equal(evaluate("prod(x,axis=0)"), prod(x,axis=0)) - assert_equal(evaluate("sum(x,axis=0)"), sum(x,axis=0))
def check_axis(self): y = arange(9.0).reshape(3,3) Index: interpreter.c =================================================================== --- interpreter.c (revisión: 2299) +++ interpreter.c (copia de trabajo) @@ -25,6 +25,9 @@ OP_AND_BBB, OP_OR_BBB,
+ OP_EQ_BBB, + OP_NE_BBB, + OP_GT_BII, OP_GE_BII, OP_EQ_BII, @@ -35,7 +38,6 @@ OP_EQ_BFF, OP_NE_BFF,
- OP_CAST_IB, OP_COPY_II, OP_ONES_LIKE_II, OP_NEG_II, @@ -47,7 +49,6 @@ OP_MOD_III, OP_WHERE_IFII,
- OP_CAST_FB, OP_CAST_FI, OP_COPY_FF, OP_ONES_LIKE_FF, @@ -70,7 +71,6 @@ OP_EQ_BCC, OP_NE_BCC,
- OP_CAST_CB, OP_CAST_CI, OP_CAST_CF, OP_ONES_LIKE_CC, @@ -115,6 +115,8 @@ break; case OP_AND_BBB: case OP_OR_BBB: + case OP_EQ_BBB: + case OP_NE_BBB: if (n == 0 || n == 1 || n == 2) return 'b'; break; case OP_GT_BII: @@ -131,10 +133,6 @@ if (n == 0) return 'b'; if (n == 1 || n == 2) return 'f'; break; - case OP_CAST_IB: - if (n == 0) return 'i'; - if (n == 1) return 'b'; - break; case OP_COPY_II: case OP_ONES_LIKE_II: case OP_NEG_II: @@ -152,10 +150,6 @@ if (n == 0 || n == 2 || n == 3) return 'i'; if (n == 1) return 'f'; break; - case OP_CAST_FB: - if (n == 0) return 'f'; - if (n == 1) return 'b'; - break; case OP_CAST_FI: if (n == 0) return 'f'; if (n == 1) return 'i'; @@ -194,10 +188,6 @@ if (n == 0) return 'b'; if (n == 1 || n == 2) return 'c'; break; - case OP_CAST_CB: - if (n == 0) return 'c'; - if (n == 1) return 'b'; - break; case OP_CAST_CI: if (n == 0) return 'c'; if (n == 1) return 'i'; @@ -1296,6 +1286,10 @@ add_op("invert_bb", OP_INVERT_BB); add_op("and_bbb", OP_AND_BBB); add_op("or_bbb", OP_OR_BBB); + + add_op("eq_bbb", OP_EQ_BBB); + add_op("ne_bbb", OP_NE_BBB); + add_op("gt_bii", OP_GT_BII); add_op("ge_bii", OP_GE_BII); add_op("eq_bii", OP_EQ_BII); @@ -1306,7 +1300,6 @@ add_op("eq_bff", OP_EQ_BFF); add_op("ne_bff", OP_NE_BFF);
- add_op("cast_ib", OP_CAST_IB); add_op("ones_like_ii", OP_ONES_LIKE_II); add_op("copy_ii", OP_COPY_II); add_op("neg_ii", OP_NEG_II); @@ -1318,7 +1311,6 @@ add_op("mod_iii", OP_MOD_III); add_op("where_ifii", OP_WHERE_IFII);
- add_op("cast_fb", OP_CAST_FB); add_op("cast_fi", OP_CAST_FI); add_op("copy_ff", OP_COPY_FF); add_op("ones_like_ff", OP_ONES_LIKE_FF); @@ -1342,7 +1334,6 @@ add_op("eq_bcc", OP_EQ_BCC); add_op("ne_bcc", OP_NE_BCC);
- add_op("cast_cb", OP_CAST_CB); add_op("cast_ci", OP_CAST_CI); add_op("cast_cf", OP_CAST_CF); add_op("copy_cc", OP_COPY_CC); Index: expressions.py =================================================================== --- expressions.py (revisión: 2299) +++ expressions.py (copia de trabajo) @@ -62,7 +62,13 @@ return kind_rank[n]
def bestConstantType(x): - for converter in bool, int, float, complex: + # Numeric conversion to boolean values is not tried because + # ``bool(1) == True`` (same for 0 and False), so 0 and 1 would be + # interpreted as booleans when ``False`` and ``True`` are already + # supported. + if isinstance(x, bool): + return bool + for converter in int, float, complex: try: y = converter(x) except StandardError, err: @@ -122,10 +128,7 @@ return a if isinstance(a, (bool, int, float, complex)): a = ConstantNode(a) - kind = a.astKind - if kind == 'bool': - kind = 'int' - return FuncNode('sum', [a, axis], kind=kind) + return FuncNode('sum', [a, axis], kind=a.astKind)
def prod_func(a, axis=-1): axis = encode_axis(axis) @@ -133,10 +136,7 @@ a = ConstantNode(a) if isinstance(a, ConstantNode): return a - kind = a.astKind - if kind == 'bool': - kind = 'int' - return FuncNode('prod', [a, axis], kind=kind) + return FuncNode('prod', [a, axis], kind=a.astKind)
@ophelper def div_op(a, b):
------------------------------------------------------------------------
------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ------------------------------------------------------------------------
_______________________________________________ Numpy-discussion mailing list Numpy-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/numpy-discussion
------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

En/na Colin J. Williams ha escrit:
Ivan Vilata i Balaguer wrote:
Hi all. The attached diff makes some changes to Numexpr support for booleans. The changes and their rationale are below.
1. New ``True`` and ``False`` boolean constants. This is so that 1 and 0 are always proper integer constants. It is also for completeness, but I don't envision any usage for them that couldn't be expressed without the constants.
I'm puzzled. Python already has constants True and False of the bool type. bool is a subclass of the int type. Any instance of the bool type can be converted to the int type.
a=1==0 type(a) <type 'bool'> int(a) 0 a False
Colin W.
2. The only comparisons supported with booleans are ``==`` and ``!=``, so that you can compare boolean variables. Just as NumPy supports complex order comparisons and Numexpr doesn't, so goes for bools. Being relatively new, I think there is no need to keep integer-boolean compatibility in Numexpr. What was the meaning of ``True > False`` or ``2 > True`` anyway?
Well, the ``True`` and ``False`` constants where not previously supported in Numexpr because they had to be defined somewhere. Now they are. Regarding the Python int and bool types and their relationships, it is a very elegant solution introduced in Python 2.3 since previous versions didn't have a proper boolean type, so the 0 and 1 ints where used for that. What I'm proposing here is, since Numexpr has a recent story and most probably there isn't much code affected by the change, why not define the boolean type as a purely logical one and leave its numeric compatibility issues out? By the way, it simplifies Numexpr's virtual machine (less casting opcodes). I admit again this looks a little baffling, of course, but I don't think it would mean many noticeable changes to the user. Regards, :: Ivan Vilata i Balaguer >qo< http://www.carabos.com/ Cárabos Coop. V. V V Enjoy Data "" ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Numpy-discussion mailing list Numpy-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/numpy-discussion

Ivan Vilata i Balaguer wrote:
En/na Colin J. Williams ha escrit:
Ivan Vilata i Balaguer wrote:
Hi all. The attached diff makes some changes to Numexpr support for booleans. The changes and their rationale are below.
1. New ``True`` and ``False`` boolean constants. This is so that 1 and 0 are always proper integer constants. It is also for completeness, but I don't envision any usage for them that couldn't be expressed without the constants.
I'm puzzled. Python already has constants True and False of the bool type. bool is a subclass of the int type. Any instance of the bool type can be converted to the int type.
a=1==0 type(a) <type 'bool'> int(a) 0 a False
Colin W.
2. The only comparisons supported with booleans are ``==`` and ``!=``, so that you can compare boolean variables. Just as NumPy supports complex order comparisons and Numexpr doesn't, so goes for bools. Being relatively new, I think there is no need to keep integer-boolean compatibility in Numexpr. What was the meaning of ``True > False`` or ``2 > True`` anyway?
Well, the ``True`` and ``False`` constants where not previously supported in Numexpr because they had to be defined somewhere. Now they are.
Regarding the Python int and bool types and their relationships, it is a very elegant solution introduced in Python 2.3 since previous versions didn't have a proper boolean type, so the 0 and 1 ints where used for that. What I'm proposing here is, since Numexpr has a recent story and most probably there isn't much code affected by the change, why not define the boolean type as a purely logical one and leave its numeric compatibility issues out? By the way, it simplifies Numexpr's virtual machine (less casting opcodes).
I admit again this looks a little baffling, of course, but I don't think it would mean many noticeable changes to the user.
Regards,
Ivan, I'm afraid I'm still baffled. Are you saying that your proposal is necessary to preserve compatibility with Python versions before 2.3? Otherwise, it appears to introduce clutter with no clear benefit. I don't find Numexpr in NumPy, are you referring to a scipy module? Colin W. ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

En/na Colin J. Williams ha escrit::
I'm afraid I'm still baffled. Are you saying that your proposal is necessary to preserve compatibility with Python versions before 2.3? Otherwise, it appears to introduce clutter with no clear benefit.
I don't find Numexpr in NumPy, are you referring to a scipy module?
From http://www.scipy.org/SciPyPackages/NumExpr: The scipy.sandbox.numexpr package supplies routines for the fast evaluation of array expressions elementwise by using a vector-based virtual machine. It's comparable to scipy.weave.blitz (in Weave), but doesn't require a separate compile step of C or C++ code. If your SciPy package doesn't include it, you can get a checkout from the repository:: $ svn co http://svn.scipy.org/svn/scipy/trunk/Lib/sandbox/numexpr Numexpr is not usable under Python <= 2.4 since it uses decorators (and maybe for other reasons), so my proposal clearly hasn't the intention on Python 2.3 compatibility. Instead, it is a simplification of Numexpr's type system by stricter boolean types. I suggest that you try Numexpr. It is a great piece of software. Cheers, :: Ivan Vilata i Balaguer >qo< http://www.carabos.com/ Cárabos Coop. V. V V Enjoy Data "" ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Numpy-discussion mailing list Numpy-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/numpy-discussion

Ivan Vilata i Balaguer wrote:
En/na Colin J. Williams ha escrit::
I'm afraid I'm still baffled. Are you saying that your proposal is necessary to preserve compatibility with Python versions before 2.3? Otherwise, it appears to introduce clutter with no clear benefit.
I don't find Numexpr in NumPy, are you referring to a scipy module?
From http://www.scipy.org/SciPyPackages/NumExpr:
The scipy.sandbox.numexpr package supplies routines for the fast evaluation of array expressions elementwise by using a vector-based virtual machine. It's comparable to scipy.weave.blitz (in Weave), but doesn't require a separate compile step of C or C++ code.
If your SciPy package doesn't include it, you can get a checkout from the repository::
$ svn co http://svn.scipy.org/svn/scipy/trunk/Lib/sandbox/numexpr
Numexpr is not usable under Python <= 2.4 since it uses decorators (and maybe for other reasons), so my proposal clearly hasn't the intention on Python 2.3 compatibility. Instead, it is a simplification of Numexpr's type system by stricter boolean types.
I suggest that you try Numexpr. It is a great piece of software. Cheers,
::
Ivan Vilata i Balaguer >qo< http://www.carabos.com/ Cárabos Coop. V. V V Enjoy Data
Ivan, Many thanks for this. It's a long time since I looked at SciPy, though I will look at Numexpr. Currently, I'm focusing on Numpy. Colin W. ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
participants (2)
-
Colin J. Williams
-
Ivan Vilata i Balaguer