[recipes] Always store numbers as doubles



commit 01b489c511ca3bbdedbe23ec42f1ad94b78d8ef0
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jun 24 17:35:35 2017 -0400

    Always store numbers as doubles
    
    We can now format doubles as mixed fractions, so no need
    for this extra complication anymore. Just drop GrNumber.

 src/gr-ingredients-list.c       |   17 ++--
 src/gr-ingredients-list.h       |    4 +-
 src/gr-ingredients-viewer-row.c |    8 +-
 src/gr-number.c                 |  180 +++++++++------------------------------
 src/gr-number.h                 |   22 +-----
 src/gr-shopping-page.c          |   19 ++--
 6 files changed, 65 insertions(+), 185 deletions(-)
---
diff --git a/src/gr-ingredients-list.c b/src/gr-ingredients-list.c
index 592bd75..a4ddc16 100644
--- a/src/gr-ingredients-list.c
+++ b/src/gr-ingredients-list.c
@@ -32,7 +32,7 @@
 
 typedef struct
 {
-        GrNumber amount;
+        double amount;
         gchar *unit;
         gchar *name;
         gchar *segment;
@@ -93,7 +93,7 @@ gr_ingredients_list_populate (GrIngredientsList  *ingredients,
                 segment = fields[3];
 
                 ing = g_new0 (Ingredient, 1);
-                gr_number_set_fraction (&ing->amount, 0, 1);
+                ing->amount = 1.0;
                 if (amount[0] != '\0' &&
                     !gr_number_parse (&ing->amount, &amount, &local_error)) {
                         g_message ("failed to parse amount '%s': %s", amount, local_error->message);
@@ -175,12 +175,11 @@ static void
 ingredient_scale_unit (Ingredient *ing, int num, int denom, GString *s)
 {
         g_autofree char *scaled = NULL;
-        GrNumber *snum;
+        double snum;
 
-        snum = gr_number_new_fraction (num, denom);
-        gr_number_multiply (&ing->amount, snum, snum);
+        snum = (double)num / (double)denom;
+        snum = snum * ing->amount;
         scaled = gr_number_format (snum);
-        g_free (snum);
 
         g_string_append (s, scaled);
         if (ing->unit) {
@@ -286,7 +285,7 @@ gr_ingredients_list_get_unit (GrIngredientsList *ingredients,
         return NULL;
 }
 
-GrNumber *
+double
 gr_ingredients_list_get_amount (GrIngredientsList *ingredients,
                                 const char        *segment,
                                 const char        *name)
@@ -298,11 +297,11 @@ gr_ingredients_list_get_amount (GrIngredientsList *ingredients,
 
                 if (g_strcmp0 (segment, ing->segment) == 0 &&
                     g_strcmp0 (name, ing->name) == 0) {
-                        return &ing->amount;
+                        return ing->amount;
                 }
         }
 
-        return NULL;
+        return 0.0;
 }
 
 
diff --git a/src/gr-ingredients-list.h b/src/gr-ingredients-list.h
index 0df6fe1..90b32e7 100644
--- a/src/gr-ingredients-list.h
+++ b/src/gr-ingredients-list.h
@@ -22,8 +22,6 @@
 
 #include <gtk/gtk.h>
 
-#include "gr-number.h"
-
 G_BEGIN_DECLS
 
 #define GR_TYPE_INGREDIENTS_LIST (gr_ingredients_list_get_type ())
@@ -48,7 +46,7 @@ char             **gr_ingredients_list_get_ingredients (GrIngredientsList  *ingr
 const char        *gr_ingredients_list_get_unit        (GrIngredientsList  *list,
                                                         const char         *segment,
                                                         const char         *ingredient);
-GrNumber          *gr_ingredients_list_get_amount      (GrIngredientsList  *list,
+double             gr_ingredients_list_get_amount      (GrIngredientsList  *list,
                                                         const char         *segment,
                                                         const char         *ingredient);
 
diff --git a/src/gr-ingredients-viewer-row.c b/src/gr-ingredients-viewer-row.c
index 8cbc63a..28521d6 100644
--- a/src/gr-ingredients-viewer-row.c
+++ b/src/gr-ingredients-viewer-row.c
@@ -342,7 +342,7 @@ parse_unit (const char  *text,
 {
         char *tmp;
         const char *str;
-        GrNumber number;
+        double number;
         g_autofree char *num = NULL;
 
         g_clear_pointer (amount, g_free);
@@ -356,7 +356,7 @@ parse_unit (const char  *text,
                 return FALSE;
         }
 
-        *amount = gr_number_format (&number);
+        *amount = gr_number_format (number);
         skip_whitespace (&tmp);
         if (tmp)
                 *unit = g_strdup (tmp);
@@ -826,12 +826,12 @@ text_changed (GObject    *object,
 {
         GtkEntry *entry = GTK_ENTRY (object);
         GrIngredientsViewerRow *row = data;
-        GrNumber number;
+        double number;
         char *text;
 
         text = (char *) gtk_entry_get_text (entry);
         gr_number_parse (&number, &text, NULL);
-        if (number.value > 1)
+        if (number > 1)
                 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (row->unit_completion), row->unit_cell, 
"text", 4, NULL);
         else
                 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (row->unit_completion), row->unit_cell, 
"text", 2, NULL);
diff --git a/src/gr-number.c b/src/gr-number.c
index f5564e7..096ecba 100644
--- a/src/gr-number.c
+++ b/src/gr-number.c
@@ -25,25 +25,6 @@
 #include "gr-number.h"
 #include "gr-utils.h"
 
-static int
-gcd (int m, int n)
-{
-        int r;
-
-        if (m == 0 && n == 0)
-                return -1;
-
-        if (m < 0) m = -m;
-        if (n < 0) n = -n;
-
-        while (n) {
-                r = m % n;
-                m = n;
-                n = r;
-        }
-
-        return m;
-}
 
 /*
  * http://www.ics.uci.edu/~eppstein/numth/frap.c
@@ -117,108 +98,37 @@ rational_approximation (double  input,
         }
 }
 
-void
-gr_number_set_fraction (GrNumber *number,
-                        int       num,
-                        int       denom)
-{
-        int g;
-
-        if (denom < 0) {
-                num = -num;
-                denom = -denom;
-        }
-        g = gcd (num, denom);
-        number->fraction = TRUE;
-        number->num = num / g;
-        number->denom = denom / g;
-        number->value = ((double) num) / ((double) denom);
-}
-
-void
-gr_number_set_float (GrNumber *number,
-                     double    value)
-{
-        number->fraction = FALSE;
-        number->num = 0;
-        number->denom = 0;
-        number->value = value;
-}
-
-GrNumber *
-gr_number_new_fraction (int num, int denom)
-{
-        GrNumber *number;
-
-        number = g_new (GrNumber, 1);
-        gr_number_set_fraction (number, num, denom);
-
-        return number;
-}
-
-GrNumber *
-gr_number_new_float (double value)
-{
-        GrNumber *number;
-
-        number = g_new (GrNumber, 1);
-        gr_number_set_float (number, value);
-
-        return number;
-}
-
-void
-gr_number_multiply (GrNumber *a1,
-                    GrNumber *a2,
-                    GrNumber *b)
-{
-        if (a1->fraction && a2->fraction)
-                gr_number_set_fraction (b, a1->num * a2->num, a1->denom * a2->denom);
-        else
-                gr_number_set_float (b, a1->value * a2->value);
-}
-
-void
-gr_number_add (GrNumber *a1,
-               GrNumber *a2,
-               GrNumber *b)
-{
-        if (a1->fraction && a2->fraction)
-                gr_number_set_fraction (b, a1->num * a2->denom + a2->num * a1->denom, a1->denom * a2->denom);
-        else
-                gr_number_set_float (b, a1->value + a2->value);
-}
-
 typedef struct {
         int num;
         int denom;
         const char *ch;
+        double value;
 } VulgarFraction;
 
 /* a workaround for poor availability of OpenType frak support in our fonts */
 static VulgarFraction fractions[] = {
-        { 1,  2, "½" },
-        { 1,  3, "⅓" },
-        { 2,  3, "⅔" },
-        { 1,  4, "¼" },
-        { 3,  4, "¾" },
-        { 1,  5, "⅕" },
-        { 2,  5, "⅖" },
-        { 3,  5, "⅗" },
-        { 4,  5, "⅘" },
-        { 1,  6, "⅙" },
-        { 5,  6, "⅚" },
-        { 1,  7, "⅐" },
-        { 1,  8, "⅛" },
-        { 3,  8, "⅜" },
-        { 5,  8, "⅝" },
-        { 7,  8, "⅞" },
-        { 1,  9, "⅑" },
-        { 1, 10, "⅒" }
+        { 1,  2, "½", 1.0/2.0 },
+        { 1,  3, "⅓", 1.0/3.0 },
+        { 2,  3, "⅔", 2.0/3.0 },
+        { 1,  4, "¼", 1.0/4.0 },
+        { 3,  4, "¾", 3.0/4.0 },
+        { 1,  5, "⅕", 1.0/5.0 },
+        { 2,  5, "⅖", 2.0/5.0 },
+        { 3,  5, "⅗", 3.0/5.0 },
+        { 4,  5, "⅘", 4.0/5.0 },
+        { 1,  6, "⅙", 1.0/6.0 },
+        { 5,  6, "⅚", 5.0/6.0 },
+        { 1,  7, "⅐", 1.0/7.0 },
+        { 1,  8, "⅛", 1.0/8.0 },
+        { 3,  8, "⅜", 3.0/8.0 },
+        { 5,  8, "⅝", 5.0/8.0 },
+        { 7,  8, "⅞", 7.0/8.0 },
+        { 1,  9, "⅑", 1.0/9.0 },
+        { 1, 10, "⅒", 1.0/10.0 }
 };
 
 static gboolean
-parse_as_vulgar_fraction (GrNumber  *number,
+parse_as_vulgar_fraction (double    *number,
                           char     **input,
                           GError   **error)
 {
@@ -228,9 +138,8 @@ parse_as_vulgar_fraction (GrNumber  *number,
                 const char *vf = fractions[i].ch;
                 if (g_str_has_prefix (*input, vf) &&
                     space_or_nul ((*input)[strlen (vf)])) {
-                        gr_number_set_fraction (number, fractions[i].num, fractions[i].denom);
+                        *number = fractions[i].value;
                         *input += strlen (vf);
-
                         return TRUE;
                 }
         }
@@ -242,7 +151,7 @@ parse_as_vulgar_fraction (GrNumber  *number,
 }
 
 static gboolean
-parse_as_fraction (GrNumber  *number,
+parse_as_fraction (double    *number,
                    char     **input,
                    GError   **error)
 {
@@ -269,14 +178,13 @@ parse_as_fraction (GrNumber  *number,
                 denom = 1;
 
         *input = end;
-
-        gr_number_set_fraction (number, (int)num, (int)denom);
+        *number = (double)num / (double)MAX(denom, 1);
 
         return TRUE;
 }
 
 static gboolean
-parse_as_integer (GrNumber  *number,
+parse_as_integer (double    *number,
                   char     **input,
                   gboolean   require_whitespace,
                   GError   **error)
@@ -292,14 +200,13 @@ parse_as_integer (GrNumber  *number,
                return FALSE;
         }
         *input = end;
-
-        gr_number_set_fraction (number, (int)num, 1);
+        *number = (double)num;
 
         return TRUE;
 }
 
 static gboolean
-parse_as_float (GrNumber  *number,
+parse_as_float (double    *number,
                 char     **input,
                 GError   **error)
 {
@@ -315,14 +222,13 @@ parse_as_float (GrNumber  *number,
                 return FALSE;
         }
         *input = end;
-
-        gr_number_set_float (number, value);
+        *number = value;
 
         return TRUE;
 }
 
 gboolean
-gr_number_parse (GrNumber  *number,
+gr_number_parse (double    *number,
                  char     **input,
                  GError   **error)
 {
@@ -339,14 +245,14 @@ gr_number_parse (GrNumber  *number,
         if (parse_as_integer (number, &orig, FALSE, NULL)) {
                 gboolean valid;
                 char *endofint;
-                GrNumber n;
+                double n;
 
                 endofint = orig;
                 valid = skip_whitespace (&orig);
 
                 if (parse_as_vulgar_fraction (&n, &orig, NULL) ||
                     parse_as_fraction (&n, &orig, NULL)) {
-                        gr_number_add (number, &n, number);
+                        *number = *number + n;
                         *input = orig;
                         return TRUE;
                 }
@@ -417,20 +323,16 @@ out:
 }
 
 char *
-gr_number_format (GrNumber *number)
+gr_number_format (double number)
 {
-        if (number->fraction)
-                return format_fraction (0, number->num, number->denom);
-        else {
-                double integral, rem;
-                int num, denom;
-
-                integral = floor (number->value);
-                rem = number->value - integral;
-
-                if (rational_approximation (rem, 20, &num, &denom))
-                        return format_fraction ((int)integral, num, denom);
-                else
-                        return g_strdup_printf ("%g", number->value);
-        }
+        double integral, rem;
+        int num, denom;
+
+        integral = floor (number);
+        rem = number - integral;
+
+        if (rational_approximation (rem, 20, &num, &denom))
+                return format_fraction ((int)integral, num, denom);
+        else
+                return g_strdup_printf ("%g", number);
 }
diff --git a/src/gr-number.h b/src/gr-number.h
index 6682edf..b6f2378 100644
--- a/src/gr-number.h
+++ b/src/gr-number.h
@@ -22,28 +22,10 @@
 
 G_BEGIN_DECLS
 
-typedef struct {
-        gboolean fraction;
-        int num, denom;
-        double value;
-} GrNumber;
-
-GrNumber *gr_number_new_fraction (int num, int denom);
-GrNumber *gr_number_new_float    (double value);
-
-void      gr_number_set_fraction (GrNumber *number, int num, int denom);
-void      gr_number_set_float    (GrNumber *number, double value);
-void      gr_number_add          (GrNumber *a1,
-                                  GrNumber *a2,
-                                  GrNumber *b);
-void      gr_number_multiply     (GrNumber *a1,
-                                  GrNumber *a2,
-                                  GrNumber *b);
-
-gboolean  gr_number_parse  (GrNumber  *number,
+gboolean  gr_number_parse  (double    *number,
                             char     **input,
                             GError   **error);
-char     *gr_number_format (GrNumber *number);
+char     *gr_number_format (double     number);
 
 
 
diff --git a/src/gr-shopping-page.c b/src/gr-shopping-page.c
index 7aa31b6..cbffdb9 100644
--- a/src/gr-shopping-page.c
+++ b/src/gr-shopping-page.c
@@ -137,7 +137,7 @@ recount_recipes (GrShoppingPage *page)
 }
 
 typedef struct {
-        GrNumber amount;
+        double amount;
         char *unit;
 } Unit;
 
@@ -191,7 +191,7 @@ ingredient_clear (Ingredient *ing)
 
 static void
 ingredient_add (Ingredient *ing,
-                GrNumber   *amount,
+                double      amount,
                 const char *unit)
 {
         int i;
@@ -201,12 +201,12 @@ ingredient_add (Ingredient *ing,
                 Unit *u = &g_array_index (ing->units, Unit, i);
 
                 if (g_strcmp0 (u->unit, unit) == 0) {
-                        gr_number_add (&u->amount, amount, &u->amount);
+                        u->amount += amount;
                         return;
                 }
         }
 
-        nu.amount = *amount;
+        nu.amount = amount;
         nu.unit = g_strdup (unit);
 
         g_array_append_val (ing->units, nu);
@@ -225,7 +225,7 @@ ingredient_format_unit (Ingredient *ing)
                 g_autofree char *num = NULL;
                 if (s->len > 0)
                         g_string_append (s, ", ");
-                num = gr_number_format (&(u->amount));
+                num = gr_number_format (u->amount);
                 g_string_append (s, num);
                 g_string_append (s, " ");
                 if (u->unit)
@@ -434,7 +434,7 @@ removed_row_activated (GtkListBox     *list,
 
 static void
 add_ingredient (GrShoppingPage *page,
-                GrNumber *amount,
+                double      amount,
                 const char *unit,
                 const char *ingredient)
 {
@@ -465,11 +465,10 @@ collect_ingredients_from_recipe (GrShoppingPage *page,
                 ing = gr_ingredients_list_get_ingredients (il, seg[i]);
                 for (j = 0; ing[j]; j++) {
                         const char *unit;
-                        GrNumber *amount, *num;
+                        double amount;
+
                         amount = gr_ingredients_list_get_amount (il, seg[i], ing[j]);
-                        num = gr_number_new_fraction (serves, gr_recipe_get_serves (recipe));
-                        gr_number_multiply (num, amount, amount);
-                        g_free (num);
+                        amount = amount * serves / (double)gr_recipe_get_serves (recipe);
                         unit = gr_ingredients_list_get_unit (il, seg[i], ing[j]);
                         add_ingredient (page, amount, unit, ing[j]);
                 }


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