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
{
exchange = gnc_numeric_div(gnc_numeric_create(1,1),
gnc_price_get_value(price),
1000, GNC_HOW_RND_ROUND_HALF_UP);
exchange = gnc_numeric_invert(gnc_price_get_value(price));
exchange = gnc_numeric_convert(exchange, 1000,
GNC_HOW_RND_ROUND_HALF_UP);
}
}
else
@ -1779,4 +1779,3 @@ GHashTable* gnc_sx_all_instantiate_cashflow_all(GDate range_start, GDate range_e
result_map, NULL);
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),
gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
price_value = gnc_numeric_div (gnc_numeric_create (1, 1), price_value,
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
price_value = gnc_numeric_invert(price_value);
}
else
{
@ -910,8 +909,7 @@ gnc_xfer_dialog_update_conv_info (XferDialog *xferData)
gtk_label_set_text(GTK_LABEL(xferData->conv_forward), string);
g_free(string);
rate = gnc_numeric_div(gnc_numeric_create (1, 1), rate,
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
rate = gnc_numeric_invert(rate);
string = g_strdup_printf("1 %s = %f %s", to_mnemonic,
gnc_numeric_to_double(rate), from_mnemonic);
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;
from_amt = to_amt;
to_amt = tmp_amt;
*value = gnc_numeric_div (gnc_numeric_create(1, 1), *value,
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
*value = gnc_numeric_invert (*value);
}
static void
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);
if (price)
{
price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
gnc_price_get_value(price),
GNC_DENOM_AUTO,
GNC_HOW_DENOM_REDUCE);
}
price_value = gnc_numeric_invert(gnc_price_get_value(price));
}
if (price)
@ -1567,9 +1560,10 @@ create_price(XferDialog *xferData, Timespec ts)
return;
}
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_set_time (price, ts);
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);
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);
/* 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);
have_price = TRUE;
}
@ -2397,9 +2390,9 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_numeric rate = xaccTransGetAccountConvRate(txn, reg_acc);
/* XXX: should we tell the user we've done the conversion? */
amount = gnc_numeric_div(
amount, rate,
gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE);
amount = gnc_numeric_div(amount, rate,
gnc_commodity_get_fraction(txn_cur),
GNC_HOW_DENOM_REDUCE);
}
/* 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_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate))
*exch_rate = gnc_numeric_div(gnc_numeric_create(1, 1), *exch_rate,
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
*exch_rate = gnc_numeric_invert(*exch_rate);
amount = gnc_numeric_neg(amount);
}
else

View File

@ -1149,7 +1149,26 @@ gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
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
********************************************************************/

View File

@ -504,6 +504,13 @@ gnc_numeric gnc_numeric_reduce(gnc_numeric n);
********************************************************************/
gboolean gnc_numeric_to_decimal(gnc_numeric * a,
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