analog: Implement division for sr_rational
This commit is contained in:
parent
ee1b6054d6
commit
17d5a11c69
|
@ -36,6 +36,8 @@ SR_API void sr_rational_set(struct sr_rational *r, int64_t p, uint64_t q);
|
||||||
SR_API int sr_rational_eq(const struct sr_rational *a, const struct sr_rational *b);
|
SR_API int sr_rational_eq(const struct sr_rational *a, const struct sr_rational *b);
|
||||||
SR_API int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a,
|
SR_API int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a,
|
||||||
const struct sr_rational *b);
|
const struct sr_rational *b);
|
||||||
|
SR_API int sr_rational_div(struct sr_rational *res, const struct sr_rational *num,
|
||||||
|
const struct sr_rational *div);
|
||||||
|
|
||||||
/*--- backend.c -------------------------------------------------------------*/
|
/*--- backend.c -------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
43
src/analog.c
43
src/analog.c
|
@ -444,6 +444,8 @@ SR_API int sr_rational_eq(const struct sr_rational *a, const struct sr_rational
|
||||||
* otherwise. If the resulting nominator/denominator are relatively prime,
|
* otherwise. If the resulting nominator/denominator are relatively prime,
|
||||||
* this may not be possible.
|
* this may not be possible.
|
||||||
*
|
*
|
||||||
|
* It is save to use the same variable for result and input values
|
||||||
|
*
|
||||||
* @retval SR_OK Success.
|
* @retval SR_OK Success.
|
||||||
* @retval SR_ERR_ARG Resulting value to large
|
* @retval SR_ERR_ARG Resulting value to large
|
||||||
*
|
*
|
||||||
|
@ -506,4 +508,45 @@ SR_API int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Divide rational a by rational b
|
||||||
|
*
|
||||||
|
* @param[in] num numerator
|
||||||
|
* @param[in] div divisor
|
||||||
|
* @param[out] res Result
|
||||||
|
*
|
||||||
|
* The resulting nominator/denominator are reduced if the result would not fit
|
||||||
|
* otherwise. If the resulting nominator/denominator are relatively prime,
|
||||||
|
* this may not be possible.
|
||||||
|
*
|
||||||
|
* It is save to use the same variable for result and input values
|
||||||
|
*
|
||||||
|
* @retval SR_OK Success.
|
||||||
|
* @retval SR_ERR_ARG Division by zero
|
||||||
|
* @retval SR_ERR_ARG Denominator of divisor to large
|
||||||
|
* @retval SR_ERR_ARG Resulting value to large
|
||||||
|
*
|
||||||
|
* @since 0.5.0
|
||||||
|
*/
|
||||||
|
SR_API int sr_rational_div(struct sr_rational *res, const struct sr_rational *num,
|
||||||
|
const struct sr_rational *div)
|
||||||
|
{
|
||||||
|
struct sr_rational t;
|
||||||
|
|
||||||
|
if (div->q > INT64_MAX)
|
||||||
|
return SR_ERR_ARG;
|
||||||
|
if (div->p == 0)
|
||||||
|
return SR_ERR_ARG;
|
||||||
|
|
||||||
|
if (div->p > 0) {
|
||||||
|
t.p = div->q;
|
||||||
|
t.q = div->p;
|
||||||
|
} else {
|
||||||
|
t.p = -div->q;
|
||||||
|
t.q = -div->p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sr_rational_mult(res, num, &t);
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -266,6 +266,50 @@ START_TEST(test_mult_rational)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_div_rational)
|
||||||
|
{
|
||||||
|
const struct sr_rational r[][3] = {
|
||||||
|
/* a * b = c */
|
||||||
|
{ { 1, 1 }, { 1, 1 }, { 1, 1 }},
|
||||||
|
{ { 2, 1 }, { 1, 3 }, { 6, 1 }},
|
||||||
|
{ { 1, 2 }, { 1, 2 }, { 1, 1 }},
|
||||||
|
/* Test negative numbers */
|
||||||
|
{ { -1, 2 }, { 1, 2 }, { -1, 1 }},
|
||||||
|
{ { -1, 2 }, { -1, 2 }, { 1, 1 }},
|
||||||
|
{ { -(1ll<<20), (1ll<<10) }, { -1, (1ll<<20) }, { (1ll<<30), 1 }},
|
||||||
|
/* Test reduction */
|
||||||
|
{ { INT32_MAX, (1ll<<12) }, { 1, (1<<2) }, { INT32_MAX, (1ll<<10) }},
|
||||||
|
{ { INT64_MAX, (1ll<<63) }, { 1, (1<<3) }, { INT64_MAX, (1ll<<60) }},
|
||||||
|
/* Test large numbers */
|
||||||
|
{ { (1ll<<40), (1ll<<10) }, { 1, (1ll<<30) }, { (1ll<<60), 1 }},
|
||||||
|
{ { -(1ll<<40), (1ll<<10) }, { -1, (1ll<<30) }, { (1ll<<60), 1 }},
|
||||||
|
|
||||||
|
{ { 10000*3, 4 }, { 1, 80000*3 }, { 200000000*9, 1 }},
|
||||||
|
{ { 4, 10000*3 }, { 80000*3, 1 }, { 1, 200000000*9 }},
|
||||||
|
|
||||||
|
{ { -10000*3, 4 }, { 1, 80000*3 }, { -200000000*9, 1 }},
|
||||||
|
{ { 10000*3, 4 }, { -1, 80000*3 }, { -200000000*9, 1 }},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(r); i++) {
|
||||||
|
struct sr_rational res;
|
||||||
|
|
||||||
|
int rc = sr_rational_div(&res, &r[i][0], &r[i][1]);
|
||||||
|
fail_unless(rc == SR_OK);
|
||||||
|
fail_unless(sr_rational_eq(&res, &r[i][2]) == 1,
|
||||||
|
"sr_rational_mult() failed: [%d] %ld/%lu != %ld/%lu.",
|
||||||
|
i, res.p, res.q, r[i][2].p, r[i][2].q);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
struct sr_rational res;
|
||||||
|
int rc = sr_rational_div(&res, &r[0][0], &((struct sr_rational){ 0, 5 }));
|
||||||
|
|
||||||
|
fail_unless(rc == SR_ERR_ARG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
Suite *suite_analog(void)
|
Suite *suite_analog(void)
|
||||||
{
|
{
|
||||||
Suite *s;
|
Suite *s;
|
||||||
|
@ -282,6 +326,7 @@ Suite *suite_analog(void)
|
||||||
tcase_add_test(tc, test_set_rational_null);
|
tcase_add_test(tc, test_set_rational_null);
|
||||||
tcase_add_test(tc, test_cmp_rational);
|
tcase_add_test(tc, test_cmp_rational);
|
||||||
tcase_add_test(tc, test_mult_rational);
|
tcase_add_test(tc, test_mult_rational);
|
||||||
|
tcase_add_test(tc, test_div_rational);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
Loading…
Reference in New Issue