]> sigrok.org Git - libsigrok.git/commitdiff
analog: Implement division for sr_rational
authorStefan Brüns <redacted>
Sat, 30 Apr 2016 23:36:23 +0000 (01:36 +0200)
committerUwe Hermann <redacted>
Mon, 16 May 2016 21:35:10 +0000 (23:35 +0200)
include/libsigrok/proto.h
src/analog.c
tests/analog.c

index bd7250571cb9c75143c59fa215b3d9fa7b5136b8..1a3fba8c048fd9f2a6ae6989a3bad3babcf04d51 100644 (file)
@@ -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_mult(struct sr_rational *res, const struct sr_rational *a,
                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 -------------------------------------------------------------*/
 
index 7c0dde1be5e9265c713371c78819b09f1189197b..7343b481e610d409d51bb45dd5f2be1a31138c77 100644 (file)
@@ -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,
  * 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 Resulting value to large
  *
@@ -506,4 +508,45 @@ SR_API int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a
 #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);
+}
+
 /** @} */
index b5f2beb8e21bfd5df43f3090258b7d5c19fc72de..3e8fd494c2c80616b012e99aed9c4a81c40aba18 100644 (file)
@@ -266,6 +266,50 @@ START_TEST(test_mult_rational)
 }
 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 *s;
@@ -282,6 +326,7 @@ Suite *suite_analog(void)
        tcase_add_test(tc, test_set_rational_null);
        tcase_add_test(tc, test_cmp_rational);
        tcase_add_test(tc, test_mult_rational);
+       tcase_add_test(tc, test_div_rational);
        suite_add_tcase(s, tc);
 
        return s;