From 0214e426a6cd2c80671bb55257e3358e737f60d3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 6 Mar 2017 16:35:30 +0100 Subject: add amount division API and test case --- src/include/taler_amount_lib.h | 14 ++++++++++++++ src/include/taler_error_codes.h | 15 +++++++++++++++ src/util/amount.c | 28 ++++++++++++++++++++++++++++ src/util/test_amount.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h index 5a59c10ce..555894f4b 100644 --- a/src/include/taler_amount_lib.h +++ b/src/include/taler_amount_lib.h @@ -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. * diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h index e47cff77c..c8a030fac 100644 --- a/src/include/taler_error_codes.h +++ b/src/include/taler_error_codes.h @@ -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. diff --git a/src/util/amount.c b/src/util/amount.c index 407232a9e..7684ddf32 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -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 */ diff --git a/src/util/test_amount.c b/src/util/test_amount.c index e176d2131..3854297dd 100644 --- a/src/util/test_amount.c +++ b/src/util/test_amount.c @@ -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; } -- cgit v1.2.3