# HG changeset patch # User Jaroslav Hajek # Date 1227618295 -3600 # Node ID c777f3ce02d87e6ddd0818b0b3a02efd82c502b9 # Parent b5f10b12344021c1c2b708d4d27437cb61b15870 smarter conversion lookup diff -r b5f10b123440 -r c777f3ce02d8 src/ChangeLog --- a/src/ChangeLog Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ChangeLog Tue Nov 25 14:04:55 2008 +0100 @@ -1,3 +1,19 @@ +2008-11-25 Jaroslav Hajek + + * ov-base.h (octave_base_value::type_conv_info): New class. + * ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, + ov-bool-sparse.h, ov-bool.cc, ov-bool.h, ov-complex.cc, ov-complex.h, + ov-cx-mat.cc, ov-cx-mat.h, ov-null-mat.cc, ov-null-mat.h, + ov-range.cc, ov-range.h, ov-re-mat.cc, ov-re-mat.h, ov-scalar.cc, + ov-scalar.h, ov-str-mat.cc, ov-str-mat.h, ov.h: + Return type_conv_info instead of type_conv_fcn from + numeric_conversion_function and numeric_demotion_function + methods. + * ov-base.cc (octave_base_value::numeric_assign): Try biased conversion + first if possible. + * ov.cc (do_binary_op): Likewise. Also, search recursively. + * ov.cc (do_cat_op): Likewise. + 2008-11-24 David Bateman * graphics.cc (F__go_delete__): Check validity of handles before diff -r b5f10b123440 -r c777f3ce02d8 src/ov-base.cc --- a/src/ov-base.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-base.cc Tue Nov 25 14:04:55 2008 +0100 @@ -1150,9 +1150,26 @@ { octave_value tmp_rhs; - octave_base_value::type_conv_fcn cf_rhs + octave_base_value::type_conv_info cf_rhs = rhs.numeric_conversion_function (); + octave_base_value::type_conv_info cf_this + = numeric_conversion_function (); + + // Try biased (one-sided) conversions first. + if (cf_rhs.type_id () >= 0 + && (octave_value_typeinfo::lookup_assign_op (octave_value::op_asn_eq, + t_lhs, cf_rhs.type_id ()) + || octave_value_typeinfo::lookup_pref_assign_conv (t_lhs, + cf_rhs.type_id ()) >= 0)) + cf_this = 0; + else if (cf_this.type_id () >= 0 + && (octave_value_typeinfo::lookup_assign_op (octave_value::op_asn_eq, + cf_this.type_id (), t_rhs) + || octave_value_typeinfo::lookup_pref_assign_conv (cf_this.type_id (), + t_rhs) >= 0)) + cf_rhs = 0; + if (cf_rhs) { octave_base_value *tmp = cf_rhs (rhs.get_rep ()); @@ -1169,9 +1186,6 @@ else tmp_rhs = rhs; - octave_base_value::type_conv_fcn cf_this - = numeric_conversion_function (); - count++; octave_value tmp_lhs = octave_value (this); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-base.h --- a/src/ov-base.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-base.h Tue Nov 25 14:04:55 2008 +0100 @@ -106,6 +106,24 @@ typedef octave_base_value * (*type_conv_fcn) (const octave_base_value&); + // type conversion, including result type information + class type_conv_info + { + public: + type_conv_info (type_conv_fcn f = 0, int t = -1) : _fcn (f), _type_id (t) { } + + operator type_conv_fcn (void) const { return _fcn; } + + octave_base_value * operator () (const octave_base_value &v) const + { return (*_fcn) (v); } + + int type_id (void) const { return _type_id; } + + private: + type_conv_fcn _fcn; + int _type_id; + }; + friend class octave_value; octave_base_value (void) : count (1) { } @@ -120,13 +138,13 @@ virtual octave_base_value * empty_clone (void) const { return new octave_base_value (); } - virtual type_conv_fcn + virtual type_conv_info numeric_conversion_function (void) const - { return static_cast (0); } + { return type_conv_info (); } - virtual type_conv_fcn + virtual type_conv_info numeric_demotion_function (void) const - { return static_cast (0); } + { return type_conv_info (); } virtual octave_value squeeze (void) const; diff -r b5f10b123440 -r c777f3ce02d8 src/ov-bool-mat.cc --- a/src/ov-bool-mat.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-bool-mat.cc Tue Nov 25 14:04:55 2008 +0100 @@ -62,10 +62,11 @@ return new octave_matrix (NDArray (v.bool_array_value ())); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_bool_matrix::numeric_conversion_function (void) const { - return default_numeric_conversion_function; + return octave_base_value::type_conv_info (default_numeric_conversion_function, + octave_matrix::static_type_id ()); } octave_base_value * diff -r b5f10b123440 -r c777f3ce02d8 src/ov-bool-mat.h --- a/src/ov-bool-mat.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-bool-mat.h Tue Nov 25 14:04:55 2008 +0100 @@ -73,7 +73,7 @@ octave_base_value *clone (void) const { return new octave_bool_matrix (*this); } octave_base_value *empty_clone (void) const { return new octave_bool_matrix (); } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; octave_base_value *try_narrowing_conversion (void); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-bool-sparse.cc --- a/src/ov-bool-sparse.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-bool-sparse.cc Tue Nov 25 14:04:55 2008 +0100 @@ -58,10 +58,11 @@ return new octave_sparse_matrix (SparseMatrix (v.sparse_bool_matrix_value ())); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_sparse_bool_matrix::numeric_conversion_function (void) const { - return default_numeric_conversion_function; + return octave_base_value::type_conv_info (default_numeric_conversion_function, + octave_sparse_matrix::static_type_id ()); } octave_base_value * diff -r b5f10b123440 -r c777f3ce02d8 src/ov-bool-sparse.h --- a/src/ov-bool-sparse.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-bool-sparse.h Tue Nov 25 14:04:55 2008 +0100 @@ -80,7 +80,7 @@ octave_base_value *clone (void) const { return new octave_sparse_bool_matrix (*this); } octave_base_value *empty_clone (void) const { return new octave_sparse_bool_matrix (); } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; octave_base_value *try_narrowing_conversion (void); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-bool.cc --- a/src/ov-bool.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-bool.cc Tue Nov 25 14:04:55 2008 +0100 @@ -58,10 +58,12 @@ return new octave_scalar (v.bool_value ()); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_bool::numeric_conversion_function (void) const { - return default_numeric_conversion_function; + return octave_base_value::type_conv_info (default_numeric_conversion_function, + octave_scalar::static_type_id ()); + } static inline bool diff -r b5f10b123440 -r c777f3ce02d8 src/ov-bool.h --- a/src/ov-bool.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-bool.h Tue Nov 25 14:04:55 2008 +0100 @@ -66,7 +66,7 @@ octave_base_value *clone (void) const { return new octave_bool (*this); } octave_base_value *empty_clone (void) const { return new octave_bool (); } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; octave_value do_index_op (const octave_value_list& idx, bool resize_ok = false); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-complex.cc --- a/src/ov-complex.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-complex.cc Tue Nov 25 14:04:55 2008 +0100 @@ -63,10 +63,11 @@ return new octave_float_complex (v.float_complex_value ()); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_complex::numeric_demotion_function (void) const { - return default_numeric_demotion_function; + return octave_base_value::type_conv_info(default_numeric_demotion_function, + octave_float_complex::static_type_id ()); } octave_base_value * diff -r b5f10b123440 -r c777f3ce02d8 src/ov-complex.h --- a/src/ov-complex.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-complex.h Tue Nov 25 14:04:55 2008 +0100 @@ -73,7 +73,7 @@ octave_base_value *empty_clone (void) const { return new octave_complex_matrix (); } - type_conv_fcn numeric_demotion_function (void) const; + type_conv_info numeric_demotion_function (void) const; octave_base_value *try_narrowing_conversion (void); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-cx-mat.cc --- a/src/ov-cx-mat.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-cx-mat.cc Tue Nov 25 14:04:55 2008 +0100 @@ -69,10 +69,11 @@ return new octave_float_complex_matrix (v.float_complex_matrix_value ()); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_complex_matrix::numeric_demotion_function (void) const { - return default_numeric_demotion_function; + return octave_base_value::type_conv_info(default_numeric_demotion_function, + octave_float_complex_matrix::static_type_id ()); } octave_base_value * diff -r b5f10b123440 -r c777f3ce02d8 src/ov-cx-mat.h --- a/src/ov-cx-mat.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-cx-mat.h Tue Nov 25 14:04:55 2008 +0100 @@ -86,7 +86,7 @@ octave_base_value *clone (void) const { return new octave_complex_matrix (*this); } octave_base_value *empty_clone (void) const { return new octave_complex_matrix (); } - type_conv_fcn numeric_demotion_function (void) const; + type_conv_info numeric_demotion_function (void) const; octave_base_value *try_narrowing_conversion (void); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-null-mat.cc --- a/src/ov-null-mat.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-null-mat.cc Tue Nov 25 14:04:55 2008 +0100 @@ -40,10 +40,11 @@ return a.empty_clone (); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_null_matrix::numeric_conversion_function (void) const { - return default_null_matrix_numeric_conversion_function; + return octave_base_value::type_conv_info (default_null_matrix_numeric_conversion_function, + octave_matrix::static_type_id ()); } DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_null_str, "null_string", "char"); @@ -58,10 +59,11 @@ return a.empty_clone (); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_null_str::numeric_conversion_function (void) const { - return default_null_str_numeric_conversion_function; + return octave_base_value::type_conv_info (default_null_str_numeric_conversion_function, + octave_char_matrix_str::static_type_id ()); } DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_null_sq_str, "null_sq_string", "char"); @@ -76,10 +78,11 @@ return a.empty_clone (); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_null_sq_str::numeric_conversion_function (void) const { - return default_null_sq_str_numeric_conversion_function; + return octave_base_value::type_conv_info (default_null_sq_str_numeric_conversion_function, + octave_char_matrix_sq_str::static_type_id ()); } DEFUN (isnull, args, , diff -r b5f10b123440 -r c777f3ce02d8 src/ov-null-mat.h --- a/src/ov-null-mat.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-null-mat.h Tue Nov 25 14:04:55 2008 +0100 @@ -47,7 +47,7 @@ bool is_null_value (void) const { return true; } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; private: @@ -68,7 +68,7 @@ bool is_null_value (void) const { return true; } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; private: @@ -90,7 +90,7 @@ bool is_null_value (void) const { return true; } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; private: diff -r b5f10b123440 -r c777f3ce02d8 src/ov-range.cc --- a/src/ov-range.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-range.cc Tue Nov 25 14:04:55 2008 +0100 @@ -54,10 +54,11 @@ return new octave_matrix (v.matrix_value ()); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_range::numeric_conversion_function (void) const { - return default_numeric_conversion_function; + return octave_base_value::type_conv_info (default_numeric_conversion_function, + octave_matrix::static_type_id ()); } octave_base_value * diff -r b5f10b123440 -r c777f3ce02d8 src/ov-range.h --- a/src/ov-range.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-range.h Tue Nov 25 14:04:55 2008 +0100 @@ -84,7 +84,7 @@ // to create an empty matrix (0x0) instead of an empty range (1x0). octave_base_value *empty_clone (void) const { return new octave_matrix (); } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; octave_base_value *try_narrowing_conversion (void); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-re-mat.cc --- a/src/ov-re-mat.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-re-mat.cc Tue Nov 25 14:04:55 2008 +0100 @@ -81,10 +81,11 @@ return new octave_float_matrix (v.float_matrix_value ()); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_matrix::numeric_demotion_function (void) const { - return default_numeric_demotion_function; + return octave_base_value::type_conv_info(default_numeric_demotion_function, + octave_float_matrix::static_type_id ()); } octave_base_value * diff -r b5f10b123440 -r c777f3ce02d8 src/ov-re-mat.h --- a/src/ov-re-mat.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-re-mat.h Tue Nov 25 14:04:55 2008 +0100 @@ -86,7 +86,7 @@ octave_base_value *clone (void) const { return new octave_matrix (*this); } octave_base_value *empty_clone (void) const { return new octave_matrix (); } - type_conv_fcn numeric_demotion_function (void) const; + type_conv_info numeric_demotion_function (void) const; octave_base_value *try_narrowing_conversion (void); diff -r b5f10b123440 -r c777f3ce02d8 src/ov-scalar.cc --- a/src/ov-scalar.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-scalar.cc Tue Nov 25 14:04:55 2008 +0100 @@ -65,10 +65,11 @@ return new octave_float_scalar (v.float_value ()); } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_scalar::numeric_demotion_function (void) const { - return default_numeric_demotion_function; + return octave_base_value::type_conv_info(default_numeric_demotion_function, + octave_float_scalar::static_type_id ()); } octave_value diff -r b5f10b123440 -r c777f3ce02d8 src/ov-scalar.h --- a/src/ov-scalar.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-scalar.h Tue Nov 25 14:04:55 2008 +0100 @@ -76,7 +76,7 @@ octave_value do_index_op (const octave_value_list& idx, bool resize_ok = false); - type_conv_fcn numeric_demotion_function (void) const; + type_conv_info numeric_demotion_function (void) const; idx_vector index_vector (void) const { return idx_vector (scalar); } diff -r b5f10b123440 -r c777f3ce02d8 src/ov-str-mat.cc --- a/src/ov-str-mat.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-str-mat.cc Tue Nov 25 14:04:55 2008 +0100 @@ -66,21 +66,16 @@ NDArray nda = v.array_value (true); - if (! error_state) - { - if (nda.numel () == 1) - retval = new octave_scalar (nda(0)); - else - retval = new octave_matrix (nda); - } + if (! error_state) retval = new octave_matrix (nda); return retval; } -octave_base_value::type_conv_fcn +octave_base_value::type_conv_info octave_char_matrix_str::numeric_conversion_function (void) const { - return default_numeric_conversion_function; + return octave_base_value::type_conv_info (default_numeric_conversion_function, + octave_matrix::static_type_id ()); } octave_value diff -r b5f10b123440 -r c777f3ce02d8 src/ov-str-mat.h --- a/src/ov-str-mat.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov-str-mat.h Tue Nov 25 14:04:55 2008 +0100 @@ -85,7 +85,7 @@ octave_base_value *clone (void) const { return new octave_char_matrix_str (*this); } octave_base_value *empty_clone (void) const { return new octave_char_matrix_str (); } - type_conv_fcn numeric_conversion_function (void) const; + type_conv_info numeric_conversion_function (void) const; octave_value do_index_op (const octave_value_list& idx, bool resize_ok = false) diff -r b5f10b123440 -r c777f3ce02d8 src/ov.cc --- a/src/ov.cc Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov.cc Tue Nov 25 14:04:55 2008 +0100 @@ -1614,7 +1614,18 @@ else { octave_value tv1; - octave_base_value::type_conv_fcn cf1 = v1.numeric_conversion_function (); + octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function (); + + octave_value tv2; + octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 && + octave_value_typeinfo::lookup_binary_op (op, t1, cf2.type_id ())) + cf1 = 0; + else if (cf1.type_id () >= 0 && + octave_value_typeinfo::lookup_binary_op (op, cf1.type_id (), t2)) + cf2 = 0; if (cf1) { @@ -1634,9 +1645,6 @@ else tv1 = v1; - octave_value tv2; - octave_base_value::type_conv_fcn cf2 = v2.numeric_conversion_function (); - if (cf2) { octave_base_value *tmp = cf2 (*v2.rep); @@ -1657,87 +1665,23 @@ if (cf1 || cf2) { - f = octave_value_typeinfo::lookup_binary_op (op, t1, t2); - - if (f) - { - try - { - retval = f (*tv1.rep, *tv2.rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } - else - { - //demote double -> single and try again - cf1 = tv1.numeric_demotion_function (); - - if (cf1) - { - octave_base_value *tmp = cf1 (*tv1.rep); - - if (tmp) - { - tv1 = octave_value (tmp); - t1 = tv1.type_id (); - } - else - { - gripe_binary_op_conv (octave_value::binary_op_as_string (op)); - return retval; - } - } - - cf2 = tv2.numeric_demotion_function (); - - if (cf2) - { - octave_base_value *tmp = cf2 (*tv2.rep); - - if (tmp) - { - tv2 = octave_value (tmp); - t2 = tv2.type_id (); - } - else - { - gripe_binary_op_conv (octave_value::binary_op_as_string (op)); - return retval; - } - } - - if (cf1 || cf2) - { - f = octave_value_typeinfo::lookup_binary_op (op, t1, t2); - - if (f) - { - try - { - retval = f (*tv1.rep, *tv2.rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } - else - gripe_binary_op (octave_value::binary_op_as_string (op), - v1.type_name (), v2.type_name ()); - } - else - gripe_binary_op (octave_value::binary_op_as_string (op), - v1.type_name (), v2.type_name ()); - } + retval = do_binary_op (op, tv1, tv2); } else { //demote double -> single and try again cf1 = tv1.numeric_demotion_function (); + cf2 = tv2.numeric_demotion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 + && octave_value_typeinfo::lookup_binary_op (op, t1, cf2.type_id ())) + cf1 = 0; + else if (cf1.type_id () >= 0 + && octave_value_typeinfo::lookup_binary_op (op, cf1.type_id (), t2)) + cf2 = 0; + if (cf1) { octave_base_value *tmp = cf1 (*tv1.rep); @@ -1754,8 +1698,6 @@ } } - cf2 = tv2.numeric_demotion_function (); - if (cf2) { octave_base_value *tmp = cf2 (*tv2.rep); @@ -1931,7 +1873,18 @@ else { octave_value tv1; - octave_base_value::type_conv_fcn cf1 = v1.numeric_conversion_function (); + octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function (); + + octave_value tv2; + octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 + && octave_value_typeinfo::lookup_cat_op (t1, cf2.type_id ())) + cf1 = 0; + else if (cf1.type_id () >= 0 + && octave_value_typeinfo::lookup_cat_op (cf1.type_id (), t2)) + cf2 = 0; if (cf1) { @@ -1951,9 +1904,6 @@ else tv1 = v1; - octave_value tv2; - octave_base_value::type_conv_fcn cf2 = v2.numeric_conversion_function (); - if (cf2) { octave_base_value *tmp = cf2 (*v2.rep); @@ -1974,21 +1924,7 @@ if (cf1 || cf2) { - f = octave_value_typeinfo::lookup_cat_op (t1, t2); - - if (f) - { - try - { - retval = f (*tv1.rep, *tv2.rep, ra_idx); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } - else - gripe_cat_op (v1.type_name (), v2.type_name ()); + retval = do_cat_op (tv1, tv2, ra_idx); } else gripe_cat_op (v1.type_name (), v2.type_name ()); @@ -2079,24 +2015,7 @@ if (tmp) { tv = octave_value (tmp); - t = tv.type_id (); - - f = octave_value_typeinfo::lookup_unary_op (op, t); - - if (f) - { - try - { - retval = f (*tv.rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } - else - gripe_unary_op (octave_value::unary_op_as_string (op), - v.type_name ()); + retval = do_unary_op (op, tv); } else gripe_unary_op_conv (octave_value::unary_op_as_string (op)); diff -r b5f10b123440 -r c777f3ce02d8 src/ov.h --- a/src/ov.h Mon Nov 24 12:57:57 2008 -0500 +++ b/src/ov.h Tue Nov 25 14:04:55 2008 +0100 @@ -315,10 +315,10 @@ int get_count (void) const { return rep->count; } - octave_base_value::type_conv_fcn numeric_conversion_function (void) const + octave_base_value::type_conv_info numeric_conversion_function (void) const { return rep->numeric_conversion_function (); } - octave_base_value::type_conv_fcn numeric_demotion_function (void) const + octave_base_value::type_conv_info numeric_demotion_function (void) const { return rep->numeric_demotion_function (); } void maybe_mutate (void);