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 _______________________________________________ Numpy-discussion mailing list Numpy-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/numpy-discussion