add amount division API and test case

This commit is contained in:
Christian Grothoff 2017-03-06 16:35:30 +01:00
parent 326f3b2a43
commit 0214e426a6
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 94 additions and 0 deletions

View File

@ -251,6 +251,20 @@ TALER_amount_add (struct TALER_Amount *sum,
const struct TALER_Amount *a2);
/**
* Divide an amount by a float. Note that this function
* may introduce a rounding error!
*
* @param result where to store @a dividend / @a divisor
* @param dividend amount to divide
* @param divisor by what to divide, must be positive
*/
void
TALER_amount_divide (struct TALER_Amount *result,
const struct TALER_Amount *dividend,
uint32_t divisor);
/**
* Normalize the given amount.
*

View File

@ -1005,6 +1005,21 @@ enum TALER_ErrorCode
*/
TALER_EC_PAY_FAILED_COMPUTE_PROPOSAL_HASH = 2123,
/**
* Failed to locate merchant's account information matching the
* wire hash given in the proposal.
* This response is
* provided with HTTP status code MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_PAY_WIRE_HASH_UNKNOWN = 2124,
/**
* We got different currencies for the wire fee and the maximum wire
* fee. This response is provided with HTTP status code
* MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_PAY_WIRE_FEE_CURRENCY_MISSMATCH = 2125,
/**
* Integer overflow with sepcified timestamp argument detected.

View File

@ -565,4 +565,32 @@ TALER_amount_to_string (const struct TALER_Amount *amount)
}
/**
* Divide an amount by a float. Note that this function
* may introduce a rounding error!
*
* @param result where to store @a dividend / @a divisor
* @param dividend amount to divide
* @param divisor by what to divide, must be positive
*/
void
TALER_amount_divide (struct TALER_Amount *result,
const struct TALER_Amount *dividend,
uint32_t divisor)
{
uint64_t modr;
GNUNET_assert (0 != divisor);
*result = *dividend;
if (1 == divisor)
return;
modr = result->value % divisor;
result->value /= divisor;
/* modr is a 32-bit value, so we can safely multiply by (<32-bit) base and add fraction! */
modr = (modr * TALER_AMOUNT_FRAC_BASE) + result->fraction;
GNUNET_assert (modr < TALER_AMOUNT_FRAC_BASE * divisor);
result->fraction = (uint32_t) (modr / divisor);
}
/* end of amount.c */

View File

@ -197,6 +197,43 @@ main(int argc,
TALER_amount_subtract (&a3, &a1, &a2));
GNUNET_assert (UINT64_MAX - 1 == a3.value);
GNUNET_assert (TALER_AMOUNT_FRAC_BASE - 1 == a3.fraction);
/* test division */
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:3.33",
&a1));
TALER_amount_divide (&a2,
&a1,
1);
GNUNET_assert (0 == strcasecmp ("EUR",
a2.currency));
GNUNET_assert (3 == a2.value);
GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 100 * 33 == a2.fraction);
TALER_amount_divide (&a2,
&a1,
3);
GNUNET_assert (0 == strcasecmp ("EUR",
a2.currency));
GNUNET_assert (1 == a2.value);
GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 100 * 11 == a2.fraction);
TALER_amount_divide (&a2,
&a1,
2);
GNUNET_assert (0 == strcasecmp ("EUR",
a2.currency));
GNUNET_assert (1 == a2.value);
GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 1000 * 665 == a2.fraction);
TALER_amount_divide (&a2,
&a1,
TALER_AMOUNT_FRAC_BASE * 2);
GNUNET_assert (0 == strcasecmp ("EUR",
a2.currency));
GNUNET_assert (0 == a2.value);
GNUNET_assert (1 == a2.fraction);
return 0;
}