[gnumeric] ExprDeriv: introspection fixes.



commit 53c161e30ee0ea8038369a45c972cb2207a68296
Author: Morten Welinder <terra gnome org>
Date:   Fri May 18 18:49:40 2018 -0400

    ExprDeriv: introspection fixes.
    
    This fixes the handler's lifetime annotation and adds introtrospection
    for the rest of the derivative api.
    
    Also fixes a cut-and-paste problem affecting derivative of a reference
    to a non-existing cell.

 plugins/fn-math/functions.c |   15 ++++--
 src/expr-deriv.c            |  113 ++++++++++++++++++++++++++++++++++++-------
 src/expr-deriv.h            |   11 +++-
 src/func-builtin.c          |    6 ++-
 src/tools/gnm-solver.c      |    2 +-
 5 files changed, 118 insertions(+), 29 deletions(-)
---
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index e880689..748a70f 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -969,7 +969,7 @@ gnumeric_exp (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 
 static GnmExpr const *
 gnumeric_exp_deriv (GnmExpr const *expr, GnmEvalPos const *ep,
-                     GnmExprDeriv *info)
+                   GnmExprDeriv *info, gpointer data)
 {
        return gnm_expr_copy (expr);
 }
@@ -1316,7 +1316,7 @@ gnumeric_ln (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 
 static GnmExpr const *
 gnumeric_ln_deriv (GnmExpr const *expr, GnmEvalPos const *ep,
-                  GnmExprDeriv *info)
+                  GnmExprDeriv *info, gpointer data)
 {
        return gnm_expr_new_binary (gnm_expr_new_constant (value_new_int (1)),
                                    GNM_EXPR_OP_DIV,
@@ -1751,7 +1751,7 @@ gnumeric_sumsq (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
 static GnmExpr const *
 gnumeric_sumsq_deriv (GnmExpr const *expr, GnmEvalPos const *ep,
-                     GnmExprDeriv *info)
+                     GnmExprDeriv *info, gpointer data)
 {
        GnmExprList *l, *args = gnm_expr_deriv_collect (expr, ep, info);
        GnmExpr const *res;
@@ -3744,13 +3744,16 @@ go_plugin_init (GOPlugin *plugin, GOCmdContext *cc)
 {
        gnm_expr_deriv_install_handler (gnm_func_lookup ("sumsq", NULL),
                                        gnumeric_sumsq_deriv,
-                                       GNM_EXPR_DERIV_NO_CHAIN);
+                                       GNM_EXPR_DERIV_NO_CHAIN,
+                                       NULL, NULL);
        gnm_expr_deriv_install_handler (gnm_func_lookup ("exp", NULL),
                                        gnumeric_exp_deriv,
-                                       GNM_EXPR_DERIV_CHAIN);
+                                       GNM_EXPR_DERIV_CHAIN,
+                                       NULL, NULL);
        gnm_expr_deriv_install_handler (gnm_func_lookup ("ln", NULL),
                                        gnumeric_ln_deriv,
-                                       GNM_EXPR_DERIV_CHAIN);
+                                       GNM_EXPR_DERIV_CHAIN,
+                                       NULL, NULL);
 }
 
 G_MODULE_EXPORT void
diff --git a/src/expr-deriv.c b/src/expr-deriv.c
index 6569774..f86d090 100644
--- a/src/expr-deriv.c
+++ b/src/expr-deriv.c
@@ -37,35 +37,82 @@ static GHashTable *deriv_handlers;
 struct DerivInfo {
        GnmExprDerivHandler handler;
        GnmExprDerivFlags flags;
+       gpointer data;
+       GDestroyNotify notify;
 };
 
+static void
+deriv_info_free (struct DerivInfo *di)
+{
+       if (di->notify)
+               di->notify (di->data);
+       g_free (di);
+}
+
 /* ------------------------------------------------------------------------- */
 
 struct GnmExprDeriv_ {
+       unsigned ref_count;
        GnmEvalPos var;
 };
 
 /**
- * gnm_expr_deriv_info_new: (skip)
+ * gnm_expr_deriv_info_new:
+ *
+ * Returns: (transfer full): A new #GnmExprDeriv.
  */
 GnmExprDeriv *
 gnm_expr_deriv_info_new (void)
 {
-       return g_new0 (GnmExprDeriv, 1);
+       GnmExprDeriv *res = g_new0 (GnmExprDeriv, 1);
+       res->ref_count = 1;
+       return res;
 }
 
 /**
- * gnm_expr_deriv_info_free: (skip)
+ * gnm_expr_deriv_info_unref:
+ * @deriv: (transfer full) (nullable): #GnmExprDeriv
  */
 void
-gnm_expr_deriv_info_free (GnmExprDeriv *deriv)
+gnm_expr_deriv_info_unref (GnmExprDeriv *deriv)
 {
+       if (!deriv || deriv->ref_count-- > 1)
+               return;
        g_free (deriv);
 }
 
+/**
+ * gnm_expr_deriv_info_ref:
+ * @deriv: (transfer none) (nullable): #GnmExprDeriv
+ *
+ * Returns: (transfer full) (nullable): a new reference to @deriv.
+ */
+GnmExprDeriv *
+gnm_expr_deriv_info_ref (GnmExprDeriv *deriv)
+{
+       if (deriv)
+               deriv->ref_count++;
+       return deriv;
+}
+
+GType
+gnm_expr_deriv_info_get_type (void)
+{
+       static GType t = 0;
+
+       if (t == 0) {
+               t = g_boxed_type_register_static ("GnmExprDeriv",
+                        (GBoxedCopyFunc)gnm_expr_deriv_info_ref,
+                        (GBoxedFreeFunc)gnm_expr_deriv_info_unref);
+       }
+       return t;
+}
+
 void
 /**
- * gnm_expr_deriv_info_set_var: (skip)
+ * gnm_expr_deriv_info_set_var:
+ * @deriv: #GnmExprDeriv
+ * @var: (transfer none): location of variable
  */
 gnm_expr_deriv_info_set_var (GnmExprDeriv *deriv, GnmEvalPos const *var)
 {
@@ -269,7 +316,8 @@ cb_arg_collect (GnmCellIter const *iter, gpointer user_)
  * @ep: evaluation position
  * @info: extra information, not currently used
  *
- * Returns: (transfer full): list of expressions expanded from @expr
+ * Returns: (type GSList) (transfer full) (element-type GnmExpr): list of
+ * expressions expanded from @expr
  */
 GnmExprList *
 gnm_expr_deriv_collect (GnmExpr const *expr,
@@ -413,7 +461,7 @@ gnm_expr_deriv (GnmExpr const *expr,
                        ? g_hash_table_lookup (deriv_handlers, f)
                        : NULL;
                GnmExpr const *res = di
-                       ? di->handler (expr, ep, info)
+                       ? di->handler (expr, ep, info, di->data)
                        : NULL;
                if (!res)
                        return NULL;
@@ -454,7 +502,7 @@ gnm_expr_deriv (GnmExpr const *expr,
 
                cell = sheet_cell_get (sheet, r.col, r.row);
                if (!cell)
-                       return gnm_expr_new_constant (value_new_float (1));
+                       return gnm_expr_new_constant (value_new_float (0));
                if (!gnm_cell_has_expr (cell))
                        return gnm_value_deriv (cell->value);
 
@@ -497,6 +545,15 @@ gnm_expr_deriv (GnmExpr const *expr,
 
 /* ------------------------------------------------------------------------- */
 
+/**
+ * gnm_expr_top_deriv:
+ * @texpr: Expression
+ * @ep: Evaluation position
+ * @info: Derivative information
+ *
+ * Returns: (transfer full) (nullable): The derivative of @texpr with
+ * respect to @info.
+ */
 GnmExprTop const *
 gnm_expr_top_deriv (GnmExprTop const *texpr,
                    GnmEvalPos const *ep,
@@ -531,6 +588,14 @@ gnm_expr_top_deriv (GnmExprTop const *texpr,
        return gnm_expr_top_new (expr);
 }
 
+/**
+ * gnm_expr_cell_deriv:
+ * @y: Result cell
+ * @x: Variable cell
+ *
+ * Returns: (transfer full) (nullable): The derivative of cell @y with
+ * respect to cell @x.
+ */
 GnmExprTop const *
 gnm_expr_cell_deriv (GnmCell *y, GnmCell *x)
 {
@@ -550,11 +615,19 @@ gnm_expr_cell_deriv (GnmCell *y, GnmCell *x)
 
        res = gnm_expr_top_deriv (y->base.texpr, &ep, info);
 
-       gnm_expr_deriv_info_free (info);
+       gnm_expr_deriv_info_unref (info);
 
        return res;
 }
 
+/**
+ * gnm_expr_cell_deriv_value:
+ * @y: Result cell
+ * @x: Variable cell
+ *
+ * Returns: The derivative of cell @y with respect to cell @x at the
+ * current value of @x.  Returns NaN on error.
+ */
 gnm_float
 gnm_expr_cell_deriv_value (GnmCell *y, GnmCell *x)
 {
@@ -585,26 +658,32 @@ gnm_expr_cell_deriv_value (GnmCell *y, GnmCell *x)
 /**
  * gnm_expr_deriv_install_handler:
  * @func: the function being given a handler
- * @h: (scope async): #GnmExprDerivHandler
+ * @h: (scope notified): #GnmExprDerivHandler
  * @flags: 
+ * @data: user data for @h
+ * @notify: destroy notification for @data
  */
 void
 gnm_expr_deriv_install_handler (GnmFunc *func, GnmExprDerivHandler h,
-                               GnmExprDerivFlags flags)
+                               GnmExprDerivFlags flags,
+                               gpointer data,
+                               GDestroyNotify notify)
 {
-       struct DerivInfo *data;
+       struct DerivInfo *hdata;
 
        if (!deriv_handlers) {
                deriv_handlers = g_hash_table_new_full
                        (g_direct_hash, g_direct_equal,
-                        NULL, g_free);
+                        NULL, (GDestroyNotify)deriv_info_free);
        }
 
-       data = g_new (struct DerivInfo, 1);
-       data->handler = h;
-       data->flags = flags;
+       hdata = g_new (struct DerivInfo, 1);
+       hdata->handler = h;
+       hdata->flags = flags;
+       hdata->data = data;
+       hdata->notify = notify;
 
-       g_hash_table_replace (deriv_handlers, func, data);
+       g_hash_table_replace (deriv_handlers, func, hdata);
 }
 
 void
diff --git a/src/expr-deriv.h b/src/expr-deriv.h
index be2e3ab..f9a01bd 100644
--- a/src/expr-deriv.h
+++ b/src/expr-deriv.h
@@ -10,8 +10,11 @@ G_BEGIN_DECLS
 
 typedef struct GnmExprDeriv_ GnmExprDeriv;
 
+GType gnm_expr_deriv_info_get_type (void);
+
 GnmExprDeriv *gnm_expr_deriv_info_new (void);
-void gnm_expr_deriv_info_free (GnmExprDeriv *deriv);
+GnmExprDeriv *gnm_expr_deriv_info_ref (GnmExprDeriv *deriv);
+void gnm_expr_deriv_info_unref (GnmExprDeriv *deriv);
 
 void gnm_expr_deriv_info_set_var (GnmExprDeriv *deriv, GnmEvalPos const *var);
 
@@ -38,14 +41,16 @@ GnmExprList *gnm_expr_deriv_collect (GnmExpr const *expr,
 
 typedef GnmExpr const * (*GnmExprDerivHandler) (GnmExpr const *expr,
                                                GnmEvalPos const *ep,
-                                               GnmExprDeriv *info);
+                                               GnmExprDeriv *info,
+                                               gpointer user);
 typedef enum {
        GNM_EXPR_DERIV_NO_CHAIN = 0x0,
        GNM_EXPR_DERIV_CHAIN = 0x1
 } GnmExprDerivFlags;
 
 void gnm_expr_deriv_install_handler (GnmFunc *func, GnmExprDerivHandler h,
-                                    GnmExprDerivFlags flags);
+                                    GnmExprDerivFlags flags,
+                                    gpointer data, GDestroyNotify notify);
 void gnm_expr_deriv_uninstall_handler (GnmFunc *func);
 void _gnm_expr_deriv_shutdown (void);
 
diff --git a/src/func-builtin.c b/src/func-builtin.c
index dc76c39..862110f 100644
--- a/src/func-builtin.c
+++ b/src/func-builtin.c
@@ -64,7 +64,8 @@ gnumeric_sum (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 static GnmExpr const *
 gnumeric_sum_deriv (GnmExpr const *expr,
                    GnmEvalPos const *ep,
-                   GnmExprDeriv *info)
+                   GnmExprDeriv *info,
+                   gpointer data)
 {
        GnmExprList *l, *args = gnm_expr_deriv_collect (expr, ep, info);
        GnmFunc *fsum = gnm_expr_get_func_def (expr);
@@ -523,7 +524,8 @@ func_builtin_init (void)
 
        gnm_expr_deriv_install_handler (gnm_func_lookup ("sum", NULL),
                                        gnumeric_sum_deriv,
-                                       GNM_EXPR_DERIV_NO_CHAIN);
+                                       GNM_EXPR_DERIV_NO_CHAIN,
+                                       NULL, NULL);
 }
 
 static void
diff --git a/src/tools/gnm-solver.c b/src/tools/gnm-solver.c
index c1e9458..16f4712 100644
--- a/src/tools/gnm-solver.c
+++ b/src/tools/gnm-solver.c
@@ -2216,7 +2216,7 @@ gnm_solver_has_analytic_hessian (GnmSolver *sol)
                }
        }
 
-       gnm_expr_deriv_info_free (info);
+       gnm_expr_deriv_info_unref (info);
 
        return sol->hessian_status == 1;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]