# HG changeset patch # User John W. Eaton # Date 1523417633 14400 # Node ID 6afed459d063e710f6d85ef9610afcaffad8af5c # Parent 5251de3c34d7ebe4b2776dfdcf74b4a14d80d596# Parent c80323fe49389dd54d4948923bedbf257a66c9d1 maint: Merge stable to default. diff -r 5251de3c34d7 -r 6afed459d063 libgui/src/variable-editor.cc --- a/libgui/src/variable-editor.cc Tue Apr 10 15:46:07 2018 -0700 +++ b/libgui/src/variable-editor.cc Tue Apr 10 23:33:53 2018 -0400 @@ -1029,12 +1029,21 @@ m_main->setCentralWidget (central_mdiarea); setWidget (m_main); - setFocusProxy (m_main); connect (this, SIGNAL (command_signal (const QString&)), p, SLOT (execute_command_in_terminal (const QString&))); } + void variable_editor::focusInEvent (QFocusEvent *ev) + { + octave_dock_widget::focusInEvent (ev); + + // set focus to the current variable + QWidget *fw = m_main->focusWidget (); + if (fw != nullptr) + fw->setFocus (); + } + // Add an action to a menu or the widget itself. QAction* diff -r 5251de3c34d7 -r 6afed459d063 libgui/src/variable-editor.h --- a/libgui/src/variable-editor.h Tue Apr 10 15:46:07 2018 -0700 +++ b/libgui/src/variable-editor.h Tue Apr 10 23:33:53 2018 -0400 @@ -334,6 +334,10 @@ void selected_command_signal (const QString& cmd); + protected: + + void focusInEvent (QFocusEvent *ev); + private: QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text, diff -r 5251de3c34d7 -r 6afed459d063 libinterp/corefcn/load-save.cc --- a/libinterp/corefcn/load-save.cc Tue Apr 10 15:46:07 2018 -0700 +++ b/libinterp/corefcn/load-save.cc Tue Apr 10 23:33:53 2018 -0400 @@ -153,12 +153,18 @@ if (global) { - scope.clear_variable (name); - scope.mark_global (name); - symtab.assign (name, val); + octave::symbol_record sym = scope.find_symbol (name); + + if (! sym.is_global ()) + { + octave::symbol_scope global_scope = symtab.global_scope (); + octave::symbol_record global_sym = global_scope.find_symbol (name); + + sym.bind_fwd_rep (global_scope.get_rep (), global_sym); + } } - else - scope.assign (name, val); + + scope.assign (name, val); } // Return TRUE if NAME matches one of the given globbing PATTERNS. diff -r 5251de3c34d7 -r 6afed459d063 libinterp/corefcn/symrec.h --- a/libinterp/corefcn/symrec.h Tue Apr 10 15:46:07 2018 -0700 +++ b/libinterp/corefcn/symrec.h Tue Apr 10 23:33:53 2018 -0400 @@ -203,7 +203,7 @@ // clear the local value. if (is_global ()) - unbind_fwd_rep (); + unbind_global_rep (); if (! (is_hidden () || is_inherited ())) { @@ -280,7 +280,7 @@ if (auto t_fwd_rep = m_fwd_rep.lock ()) return t_fwd_rep->is_global (); - return m_storage_class & global; + return is_marked_global (); } bool is_persistent (void) const @@ -363,6 +363,11 @@ m_storage_class |= global; } + bool is_marked_global (void) const + { + return m_storage_class & global; + } + void mark_persistent (void) { if (auto t_fwd_rep = m_fwd_rep.lock ()) @@ -482,51 +487,51 @@ if (auto t_fwd_rep = m_fwd_rep.lock ()) { + // If this is the symbol in the global scope, then don't + // forward again! + + if (t_fwd_rep->is_marked_global ()) + return; + t_fwd_rep->bind_fwd_rep (fwd_scope, fwd_rep); - return; } m_fwd_scope = fwd_scope; m_fwd_rep = fwd_rep; } - void unbind_fwd_rep (bool recurse = true) + void unbind_fwd_rep (void) { - // When unbinding variables in a script scope, recurse will be - // false and we will only break the immediate link. By doing - // that, we ensure that any variables that are made global in - // a script remain linked as globals in the enclosing scope. - - // When unbinding variables in a (possibly nested) function - // scope, recurse will be true and we will break the link to - // the global scope, not just the immediate link to the parent - // scope of the nested function. - - if (recurse) - { - if (auto t_fwd_rep = m_fwd_rep.lock ()) - { - // Currently, it is only possible to have at most two - // levels of indirection here, either - // - // nested function -> parent function -> global scope - // - // or - // - // script -> top level scope -> global scope - // - // so we can break the recursion here by setting the - // argument to unbind_fwd_rep to false. - - t_fwd_rep->unbind_fwd_rep (false); - return; - } - } + // When unbinding variables in a script scope, we only break + // the immediate link. By doing that, we ensure that any + // variables that are made global in a script remain linked as + // globals in the enclosing scope. m_fwd_scope = std::weak_ptr (); m_fwd_rep.reset (); } + void unbind_global_rep (void) + { + // Break the link to the global symbol_record_rep. These must + // forwarded, so we don't do anything unless the forward rep + // points to something. + + if (auto t_fwd_rep = m_fwd_rep.lock ()) + { + if (t_fwd_rep->is_marked_global ()) + { + // The rep this object points to is in the global + // scope, so delete the link to it. + + m_fwd_scope = std::weak_ptr (); + m_fwd_rep.reset (); + } + else + t_fwd_rep->unbind_fwd_rep (); + } + } + std::shared_ptr dup (const std::shared_ptr& new_scope) const; @@ -657,7 +662,6 @@ void mark_formal (void) { m_rep->mark_formal (); } void mark_hidden (void) { m_rep->mark_hidden (); } void mark_inherited (void) { m_rep->mark_inherited (); } - void mark_global (void) { m_rep->mark_global (); } void mark_persistent (void) { m_rep->mark_persistent (); } void mark_added_static (void) { m_rep->mark_added_static (); } @@ -669,6 +673,9 @@ void unmark_persistent (void) { m_rep->unmark_persistent (); } void unmark_added_static (void) { m_rep->unmark_added_static (); } + bool is_marked_global (void) const { return m_rep->is_marked_global (); } + void mark_global (void) { m_rep->mark_global (); } + void init_persistent (void) { m_rep->init_persistent (); } unsigned int storage_class (void) const { return m_rep->storage_class (); } @@ -679,7 +686,7 @@ m_rep->bind_fwd_rep (fwd_scope, sr.m_rep); } - void unbind_fwd_rep (bool recurse = true) { m_rep->unbind_fwd_rep (recurse); } + void unbind_fwd_rep (void) { m_rep->unbind_fwd_rep (); } octave_value dump (context_id context) const { diff -r 5251de3c34d7 -r 6afed459d063 libinterp/corefcn/symscope.cc --- a/libinterp/corefcn/symscope.cc Tue Apr 10 15:46:07 2018 -0700 +++ b/libinterp/corefcn/symscope.cc Tue Apr 10 23:33:53 2018 -0400 @@ -237,6 +237,6 @@ symbol_scope_rep::unbind_script_symbols (void) { for (auto& nm_sr : m_symbols) - nm_sr.second.unbind_fwd_rep (false); + nm_sr.second.unbind_fwd_rep (); } } diff -r 5251de3c34d7 -r 6afed459d063 libinterp/corefcn/symscope.h --- a/libinterp/corefcn/symscope.h Tue Apr 10 15:46:07 2018 -0700 +++ b/libinterp/corefcn/symscope.h Tue Apr 10 23:33:53 2018 -0400 @@ -792,6 +792,10 @@ m_rep->mark_hidden (name); } + // This function should only be called for the global + // symbol_scope, and that should only happen when it is added to + // the global symbol_scope. + void mark_global (const std::string& name) { if (m_rep) diff -r 5251de3c34d7 -r 6afed459d063 scripts/sparse/bicg.m --- a/scripts/sparse/bicg.m Tue Apr 10 15:46:07 2018 -0700 +++ b/scripts/sparse/bicg.m Tue Apr 10 23:33:53 2018 -0400 @@ -106,7 +106,8 @@ ## difference between the current iteration @var{x} and the previous is less ## than @code{eps * norm (@var{x},2)}. ## -## @item 4: The algorithm can't continue due to a division by zero. +## @item 4: The algorithm could not continue because intermediate values +## became too small or too large for reliable computation. ## @end itemize ## ## @item @@ -271,11 +272,12 @@ while ((flag != 2) && (iter < maxit) && (resvec(iter+1) >= norm_b * tol)) v = Afun (p, "notransp", varargin{:}); prod_qv = q' * v; - if (prod_qv == 0) + alpha = (s0' * prec_r0); + if (abs (prod_qv) <= eps * abs (alpha)) flag = 4; break endif - alpha = (s0' * prec_r0) / prod_qv; + alpha ./= prod_qv; x += alpha * p; prod_rs = (s0' * prec_r0); # Product between r0 and s0 r0 -= alpha * v; @@ -283,6 +285,12 @@ prec_r0 = M1fun (r0, "notransp", varargin{:}); prec_s0 = s0; prec_r0 = M2fun (prec_r0, "notransp", varargin{:}); + beta = s0' * prec_r0; + if (abs (prod_rs) <= abs (beta)) + flag = 4; + break; + endif + beta ./= prod_rs; prec_s0 = M2fun (prec_s0, "transp", varargin{:}); prec_s0 = M1fun (prec_s0, "transp", varargin{:}); iter += 1; @@ -295,11 +303,6 @@ flag = 3; break; endif - if (prod_rs == 0) - flag = 4; - break; - endif - beta = (s0' * prec_r0) / prod_rs; p = prec_r0 + beta*p; q = prec_s0 + conj (beta) * q; endwhile diff -r 5251de3c34d7 -r 6afed459d063 test/bug-53599.tst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug-53599.tst Tue Apr 10 23:33:53 2018 -0400 @@ -0,0 +1,23 @@ +%!function rval = sggval (val) +%! global gval +%! if (nargin == 1) +%! gval = val; +%! else +%! rval = gval; +%! endif +%!endfunction + +%!test +%! global gval +%! assert (isempty (gval)) +%! sggval (13); +%! assert (sggval (), 13); +%! assert (gval, 13); +%! clear global gval +%! assert (sggval (), []) +%! gval = 42; +%! assert (sggval (), []); +%! clear gval +%! global gval +%! gval = 42; +%! assert (sggval (), 42); diff -r 5251de3c34d7 -r 6afed459d063 test/module.mk --- a/test/module.mk Tue Apr 10 15:46:07 2018 -0700 +++ b/test/module.mk Tue Apr 10 23:33:53 2018 -0400 @@ -12,6 +12,7 @@ %reldir%/bug-38576.tst \ %reldir%/bug-46330.tst \ %reldir%/bug-49904.tst \ + %reldir%/bug-53599.tst \ %reldir%/colormaps.tst \ %reldir%/command.tst \ %reldir%/complex.tst \