Changes to bools under Numexpr
Colin J. Williams
cjw at sympatico.ca
Thu Oct 26 14:35:06 EDT 2006
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 at 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
More information about the NumPy-Discussion
mailing list