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
                                  ""
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):

Attachment: signature.asc
Description: OpenPGP digital signature

-------------------------------------------------------------------------
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

Reply via email to