[recipes] Always store numbers as doubles
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes] Always store numbers as doubles
- Date: Sun, 25 Jun 2017 03:30:17 +0000 (UTC)
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]