aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-03-06 16:35:30 +0100
committerChristian Grothoff <christian@grothoff.org>2017-03-06 16:35:30 +0100
commit0214e426a6cd2c80671bb55257e3358e737f60d3 (patch)
treec0acf2e8d730637482c6030647d01b17681a7413
parent326f3b2a43d9e18938cb2ac902b4cc9c7423f393 (diff)
add amount division API and test case
-rw-r--r--src/include/taler_amount_lib.h14
-rw-r--r--src/include/taler_error_codes.h15
-rw-r--r--src/util/amount.c28
-rw-r--r--src/util/test_amount.c37
4 files changed, 94 insertions, 0 deletions
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
@@ -252,6 +252,20 @@ TALER_amount_add (struct TALER_Amount *sum,
/**
+ * 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.
*
* @param amount amount to normalize
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;
}