Provide gnc_numeric_invert() convenience function.

Clearer and faster than dividing into 1/1.
This commit is contained in:
John Ralls 2015-08-28 19:21:37 +01:00
parent be5b9f2b84
commit f79a3af4a2
4 changed files with 45 additions and 28 deletions

View File

@ -1170,9 +1170,9 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
} }
else else
{ {
exchange = gnc_numeric_div(gnc_numeric_create(1,1), exchange = gnc_numeric_invert(gnc_price_get_value(price));
gnc_price_get_value(price), exchange = gnc_numeric_convert(exchange, 1000,
1000, GNC_HOW_RND_ROUND_HALF_UP); GNC_HOW_RND_ROUND_HALF_UP);
} }
} }
else else
@ -1779,4 +1779,3 @@ GHashTable* gnc_sx_all_instantiate_cashflow_all(GDate range_start, GDate range_e
result_map, NULL); result_map, NULL);
return result_map; return result_map;
} }

View File

@ -250,8 +250,7 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
{ {
PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to), PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from)); gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
price_value = gnc_numeric_div (gnc_numeric_create (1, 1), price_value, price_value = gnc_numeric_invert(price_value);
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
} }
else else
{ {
@ -910,8 +909,7 @@ gnc_xfer_dialog_update_conv_info (XferDialog *xferData)
gtk_label_set_text(GTK_LABEL(xferData->conv_forward), string); gtk_label_set_text(GTK_LABEL(xferData->conv_forward), string);
g_free(string); g_free(string);
rate = gnc_numeric_div(gnc_numeric_create (1, 1), rate, rate = gnc_numeric_invert(rate);
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
string = g_strdup_printf("1 %s = %f %s", to_mnemonic, string = g_strdup_printf("1 %s = %f %s", to_mnemonic,
gnc_numeric_to_double(rate), from_mnemonic); gnc_numeric_to_double(rate), from_mnemonic);
gtk_label_set_text(GTK_LABEL(xferData->conv_reverse), string); gtk_label_set_text(GTK_LABEL(xferData->conv_reverse), string);
@ -1509,8 +1507,7 @@ swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
tmp_amt = from_amt; tmp_amt = from_amt;
from_amt = to_amt; from_amt = to_amt;
to_amt = tmp_amt; to_amt = tmp_amt;
*value = gnc_numeric_div (gnc_numeric_create(1, 1), *value, *value = gnc_numeric_invert (*value);
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
} }
static void static void
create_price(XferDialog *xferData, Timespec ts) create_price(XferDialog *xferData, Timespec ts)
@ -1543,12 +1540,8 @@ create_price(XferDialog *xferData, Timespec ts)
{ {
price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts); price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
if (price) if (price)
{
price_value = gnc_numeric_div (gnc_numeric_create(1, 1), price_value = gnc_numeric_invert(gnc_price_get_value(price));
gnc_price_get_value(price),
GNC_DENOM_AUTO,
GNC_HOW_DENOM_REDUCE);
}
} }
if (price) if (price)
@ -1567,9 +1560,10 @@ create_price(XferDialog *xferData, Timespec ts)
return; return;
} }
if (!gnc_numeric_eq(price_value, gnc_price_get_value(price))) if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
value = gnc_numeric_div (gnc_numeric_create(1, 1), value, {
PRECISION, GNC_HOW_DENOM_REDUCE); value = gnc_numeric_invert(value);
value = gnc_numeric_convert(value, PRECISION, GNC_HOW_DENOM_REDUCE);
}
gnc_price_begin_edit (price); gnc_price_begin_edit (price);
gnc_price_set_time (price, ts); gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG); gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
@ -1788,10 +1782,9 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from); prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from);
if (prc) if (prc)
{ {
rate = gnc_numeric_div (gnc_numeric_create (1, 1), gnc_price_get_value (prc),
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate); gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate);
/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
rate = gnc_numeric_invert(gnc_price_get_value (prc));
gnc_price_unref (prc); gnc_price_unref (prc);
have_price = TRUE; have_price = TRUE;
} }
@ -2397,9 +2390,9 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_numeric rate = xaccTransGetAccountConvRate(txn, reg_acc); gnc_numeric rate = xaccTransGetAccountConvRate(txn, reg_acc);
/* XXX: should we tell the user we've done the conversion? */ /* XXX: should we tell the user we've done the conversion? */
amount = gnc_numeric_div( amount = gnc_numeric_div(amount, rate,
amount, rate, gnc_commodity_get_fraction(txn_cur),
gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE); GNC_HOW_DENOM_REDUCE);
} }
/* enter the accounts */ /* enter the accounts */
@ -2408,8 +2401,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_xfer_dialog_select_to_currency(xfer, txn_cur); gnc_xfer_dialog_select_to_currency(xfer, txn_cur);
gnc_xfer_dialog_select_from_currency(xfer, xfer_com); gnc_xfer_dialog_select_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate)) if (!gnc_numeric_zero_p(*exch_rate))
*exch_rate = gnc_numeric_div(gnc_numeric_create(1, 1), *exch_rate, *exch_rate = gnc_numeric_invert(*exch_rate);
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
amount = gnc_numeric_neg(amount); amount = gnc_numeric_neg(amount);
} }
else else

View File

@ -1149,7 +1149,26 @@ gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
return TRUE; return TRUE;
} }
gnc_numeric
gnc_numeric_invert(gnc_numeric num)
{
if (num.num == 0)
return gnc_numeric_zero();
if (num.denom > 0)
{
if (num.num < 0)
return gnc_numeric_create (-num.denom, -num.num);
return gnc_numeric_create (num.denom, num.num);
}
else /* Negative denominator means multiply instead of divide. */
{
int64_t mult = (num.num < 0 ? INT64_C(-1) : INT64_C(1));
qofint128 denom = mult128(-num.denom, mult * num.num);
if (denom.hi)
return gnc_numeric_error(GNC_ERROR_OVERFLOW);
return gnc_numeric_create (mult, denom.lo);
}
}
/* ******************************************************************* /* *******************************************************************
* double_to_gnc_numeric * double_to_gnc_numeric
********************************************************************/ ********************************************************************/

View File

@ -504,6 +504,13 @@ gnc_numeric gnc_numeric_reduce(gnc_numeric n);
********************************************************************/ ********************************************************************/
gboolean gnc_numeric_to_decimal(gnc_numeric * a, gboolean gnc_numeric_to_decimal(gnc_numeric * a,
guint8 * max_decimal_places); guint8 * max_decimal_places);
/** Invert a gnc_numeric.
* Much faster than dividing 1 by it.
* @param num The number to be inverted
* @return a gnc_numeric that is the inverse of num
*/
gnc_numeric gnc_numeric_invert (gnc_numeric num);
/** @} */ /** @} */
/** @name GValue /** @name GValue