Selaa lähdekoodia

Moving back continued fractions stuff to wiener.c.

Michele Orrù 11 vuotta sitten
vanhempi
commit
a4b86a069a

+ 0 - 29
src/questions/include/qarith.h

@@ -7,35 +7,6 @@
 
 #define BN_abs(a)  BN_set_negative(a, 0)
 
-
-/**
- * Fractions made of bignums.
- */
-typedef struct bigfraction {
-  BIGNUM* h;   /**< numerator */
-  BIGNUM* k;   /**< denominator */
-} bigfraction_t;
-
-
-typedef struct cf {
-  bigfraction_t fs[3];
-  short i;
-  bigfraction_t x;
-  BIGNUM* a;
-  BN_CTX* ctx;
-} cf_t;
-
-
-/* continued fractions utilities. */
-cf_t* cf_new(void);
-
-cf_t* cf_init(cf_t *f, BIGNUM *num, BIGNUM *b);
-
-void cf_free(cf_t* f);
-
-bigfraction_t* cf_next(cf_t *f);
-
-
 BIGNUM* BN_min(BIGNUM *a, BIGNUM *b);
 
 /* square root calculation */

+ 27 - 0
src/questions/include/qwiener.h

@@ -1,5 +1,32 @@
 #ifndef _QA_WIENER_H_
 #define _QA_WIENER_H
+/**
+ * Fractions made of bignums.
+ */
+typedef struct bigfraction {
+  BIGNUM* h;   /**< numerator */
+  BIGNUM* k;   /**< denominator */
+} bigfraction_t;
+
+
+typedef struct cf {
+  bigfraction_t fs[3];
+  short i;
+  bigfraction_t x;
+  BIGNUM* a;
+  BN_CTX* ctx;
+} cf_t;
+
+
+/* continued fractions utilities. */
+cf_t* cf_new(void);
+
+cf_t* cf_init(cf_t *f, BIGNUM *num, BIGNUM *b);
+
+void cf_free(cf_t* f);
+
+bigfraction_t* cf_next(cf_t *f);
+
 
 extern struct qa_question WienerQuestion;
 

+ 0 - 121
src/questions/qarith.c

@@ -22,127 +22,6 @@ const BIGNUM *BN_value_two(void)
   return &const_two;
 }
 
-cf_t* cf_new(void)
-{
-  cf_t *f;
-
-  f = (cf_t *) malloc(sizeof(cf_t));
-
-  size_t i;
-
-  for (i=0; i!=3; i++) {
-    f->fs[i].h = BN_new();
-    f->fs[i].k = BN_new();
-  }
-  f->a = BN_new();
-  f->x.h = BN_new();
-  f->x.k = BN_new();
-
-  f->ctx = BN_CTX_new();
-
-  return f;
-}
-
-void cf_free(cf_t* f)
-{
-  size_t i;
-
-  for (i=0; i!=3; i++) {
-    BN_free(f->fs[i].h);
-    BN_free(f->fs[i].k);
-  }
-  BN_free(f->a);
-  BN_free(f->x.h);
-  BN_free(f->x.k);
-
-  free(f);
-}
-
-
-/**
- * \brief Initialized a continued fraction.
- *
- * A continued fraction for a floating number x can be expressed as a series
- *  <a₀; a₁, a₂…, aₙ>
- * such that
- * <pre>
- *
- *                1
- *  x = a₀ + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
- *                    1
- *           a₁ + ⎽⎽⎽⎽⎽⎽⎽⎽⎽
- *                 a₂ + …
- *
- * </pre>
- * , where for each i < n, there exists an approximation hᵢ / kᵢ.
- * By definition,
- *   a₋₁ = 0
- *   h₋₁ = 1    h₋₂ = 0
- *   k₋₁ = 0    k₋₂ = 1
- *
- * \param f     A continued fraction structure. If f is NULL, a new one is
- *              allocated.
- * \param num   Numerator to be used as initial numerator for the fraction to be
- *              approximated.
- * \param den   Denominator to be used as denominator for the fraction to be
- *              approximated.
- *
- * \return the continued fraction fiven as input.
- */
-cf_t* cf_init(cf_t* f, BIGNUM* num, BIGNUM* den)
-{
-  if (!f) f = cf_new();
-
-  BN_zero(f->fs[0].h);
-  BN_one(f->fs[0].k);
-
-  BN_one(f->fs[1].h);
-  BN_zero(f->fs[1].k);
-
-  f->i = 2;
-  if (!BN_copy(f->x.h, num)) return NULL;
-  if (!BN_copy(f->x.k, den)) return NULL;
-
-  return f;
-}
-
-
-/**
- * \brief Produces the next fraction.
- *
- * Each new approximation hᵢ/kᵢ is defined rec ursively as:
- *   hᵢ = aᵢhᵢ₋₁ + hᵢ₋₂
- *   kᵢ = aᵢkᵢ₋₁ + kᵢ₋₂
- * Meanwhile each new aᵢ is simply the integer part of x.
- *
- *
- * \param f   The continued fraction.
- * \return NULL if the previous fraction approximates at its best the number,
- *         a pointer to the next fraction in the series othw.
- */
-bigfraction_t* cf_next(cf_t *f)
-{
-  bigfraction_t *ith_fs = &f->fs[f->i];
-  BIGNUM* rem = BN_new();
-
-  if (BN_is_zero(f->x.h)) return NULL;
-  BN_div(f->a, rem, f->x.h, f->x.k, f->ctx);
-
-  /* computing hᵢ */
-  BN_mul(f->fs[f->i].h , f->a, f->fs[(f->i-1+3) % 3].h, f->ctx);
-  BN_uadd(f->fs[f->i].h, f->fs[f->i].h, f->fs[(f->i-2+3) % 3].h);
-  /* computing kᵢ */
-  BN_mul(f->fs[f->i].k , f->a, f->fs[(f->i-1+3) % 3].k, f->ctx);
-  BN_uadd(f->fs[f->i].k, f->fs[f->i].k, f->fs[(f->i-2+3) % 3].k);
-
-  f->i = (f->i + 1) % 3;
-  /* update x. */
-  BN_copy(f->x.h, f->x.k);
-  BN_copy(f->x.k, rem);
-
-  return ith_fs;
-}
-
 /**
  * \brief Square Root for bignums.
  *

+ 0 - 100
src/questions/tests/test_qarith.c

@@ -5,106 +5,6 @@
 
 #include "qa/questions/qarith.h"
 
-
-/**
- * \brief Testing the continued fractions generator.
- *
- *
- */
-void test_cf(void)
-{
-  bigfraction_t x = {NULL, NULL};
-  cf_t* f;
-  size_t i;
-  bigfraction_t *it;
-  BIGNUM* expected;
-
-  f = cf_new();
-  x.h = BN_new();
-  x.k = BN_new();
-  expected = BN_new();
-
-   /*
-   *  Testing aᵢ
-   *
-   *              1
-   * √2 = 1 + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
-   *                  1
-   *           2 +  ⎽⎽⎽⎽⎽⎽
-   *                 2 + …
-   *
-   */
-  BN_dec2bn(&x.h, "14142135623730951");
-  BN_dec2bn(&x.k, "10000000000000000");
-  BN_dec2bn(&expected, "2");
-  cf_init(f, x.h, x.k);
-
-  it = cf_next(f);
-  assert(BN_is_one(f->a));
-  for (i=0; i!=5 && it; i++) {
-    it = cf_next(f);
-    assert(!BN_cmp(f->a, expected));
-  }
-  assert(i==5);
-
-  /*
-   * Testing hᵢ/kᵢ
-   *
-   *                        1
-   * φ = (1+√5)/2  = 1 + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
-   *                            1
-   *                      1 + ⎽⎽⎽⎽⎽
-   *                          1 + …
-   */
-  const char* fib[] = {"1", "1", "2", "3", "5", "8", "13"};
-  BN_dec2bn(&x.h, "323606797749979");
-  BN_dec2bn(&x.k, "200000000000000");
-  cf_init(f, x.h, x.k);
-  it = cf_next(f);
-  for (i=1; i!=7; i++) {
-    BN_dec2bn(&expected, fib[i]);
-    assert(!BN_cmp(it->h, expected));
-
-    BN_dec2bn(&expected, fib[i-1]);
-    assert(!BN_cmp(it->k, expected));
-
-    it=cf_next(f);
-  }
-
-  BN_dec2bn(&x.h, "60728973");
-  BN_dec2bn(&x.k, "160523347");
-  cf_init(f, x.h, x.k);
-  /* 0 */
-  it = cf_next(f);
-  /* 1 / 2 */
-  it = cf_next(f);
-  BN_dec2bn(&expected, "2");
-  assert(BN_is_one(it->h) && !BN_cmp(it->k, expected));
-  /* 1 / 3 */
-  it = cf_next(f);
-  BN_dec2bn(&expected, "3");
-  assert(BN_is_one(it->h) && !BN_cmp(it->k, expected));
-  /* 2 / 5 */
-  it = cf_next(f);
-  BN_dec2bn(&expected, "2");
-  assert(!BN_cmp(expected, it->h));
-  BN_dec2bn(&expected, "5");
-  assert(!BN_cmp(expected, it->k));
-  /* 3 / 8 */
-  it = cf_next(f);
-  BN_dec2bn(&expected, "3");
-  assert(!BN_cmp(expected, it->h));
-  BN_dec2bn(&expected, "8");
-  assert(!BN_cmp(expected, it->k));
-  /* 14/ 37 */
-  it = cf_next(f);
-  BN_dec2bn(&expected, "14");
-  assert(!BN_cmp(expected, it->h));
-  BN_dec2bn(&expected, "37");
-  assert(!BN_cmp(expected, it->k));
-}
-
-
 static void test_BN_sqrtmod(void)
 {
   BIGNUM *a, *b, *expected;

+ 97 - 0
src/questions/tests/test_wiener.c

@@ -13,6 +13,103 @@
 #include "qa/questions/questions.h"
 #include "qa/questions/qwiener.h"
 
+/**
+ * \brief Testing the continued fractions generator.
+ *
+ *
+ */
+void test_cf(void)
+{
+  bigfraction_t x = {NULL, NULL};
+  cf_t* f;
+  size_t i;
+  bigfraction_t *it;
+  BIGNUM* expected;
+
+  f = cf_new();
+  x.h = BN_new();
+  x.k = BN_new();
+  expected = BN_new();
+
+   /*
+   *  Testing aᵢ
+   *
+   *              1
+   * √2 = 1 + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
+   *                  1
+   *           2 +  ⎽⎽⎽⎽⎽⎽
+   *                 2 + …
+   *
+   */
+  BN_dec2bn(&x.h, "14142135623730951");
+  BN_dec2bn(&x.k, "10000000000000000");
+  BN_dec2bn(&expected, "2");
+  cf_init(f, x.h, x.k);
+
+  it = cf_next(f);
+  assert(BN_is_one(f->a));
+  for (i=0; i!=5 && it; i++) {
+    it = cf_next(f);
+    assert(!BN_cmp(f->a, expected));
+  }
+  assert(i==5);
+
+  /*
+   * Testing hᵢ/kᵢ
+   *
+   *                        1
+   * φ = (1+√5)/2  = 1 + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
+   *                            1
+   *                      1 + ⎽⎽⎽⎽⎽
+   *                          1 + …
+   */
+  const char* fib[] = {"1", "1", "2", "3", "5", "8", "13"};
+  BN_dec2bn(&x.h, "323606797749979");
+  BN_dec2bn(&x.k, "200000000000000");
+  cf_init(f, x.h, x.k);
+  it = cf_next(f);
+  for (i=1; i!=7; i++) {
+    BN_dec2bn(&expected, fib[i]);
+    assert(!BN_cmp(it->h, expected));
+
+    BN_dec2bn(&expected, fib[i-1]);
+    assert(!BN_cmp(it->k, expected));
+
+    it=cf_next(f);
+  }
+
+  BN_dec2bn(&x.h, "60728973");
+  BN_dec2bn(&x.k, "160523347");
+  cf_init(f, x.h, x.k);
+  /* 0 */
+  it = cf_next(f);
+  /* 1 / 2 */
+  it = cf_next(f);
+  BN_dec2bn(&expected, "2");
+  assert(BN_is_one(it->h) && !BN_cmp(it->k, expected));
+  /* 1 / 3 */
+  it = cf_next(f);
+  BN_dec2bn(&expected, "3");
+  assert(BN_is_one(it->h) && !BN_cmp(it->k, expected));
+  /* 2 / 5 */
+  it = cf_next(f);
+  BN_dec2bn(&expected, "2");
+  assert(!BN_cmp(expected, it->h));
+  BN_dec2bn(&expected, "5");
+  assert(!BN_cmp(expected, it->k));
+  /* 3 / 8 */
+  it = cf_next(f);
+  BN_dec2bn(&expected, "3");
+  assert(!BN_cmp(expected, it->h));
+  BN_dec2bn(&expected, "8");
+  assert(!BN_cmp(expected, it->k));
+  /* 14/ 37 */
+  it = cf_next(f);
+  BN_dec2bn(&expected, "14");
+  assert(!BN_cmp(expected, it->h));
+  BN_dec2bn(&expected, "37");
+  assert(!BN_cmp(expected, it->k));
+}
 
 void test_wiener(void)
 {

+ 120 - 0
src/questions/wiener.c

@@ -20,6 +20,126 @@
 #include "qa/questions/qarith.h"
 #include "qa/questions/qwiener.h"
 
+cf_t* cf_new(void)
+{
+  cf_t *f;
+
+  f = (cf_t *) malloc(sizeof(cf_t));
+
+  size_t i;
+
+  for (i=0; i!=3; i++) {
+    f->fs[i].h = BN_new();
+    f->fs[i].k = BN_new();
+  }
+  f->a = BN_new();
+  f->x.h = BN_new();
+  f->x.k = BN_new();
+
+  f->ctx = BN_CTX_new();
+
+  return f;
+}
+
+void cf_free(cf_t* f)
+{
+  size_t i;
+
+  for (i=0; i!=3; i++) {
+    BN_free(f->fs[i].h);
+    BN_free(f->fs[i].k);
+  }
+  BN_free(f->a);
+  BN_free(f->x.h);
+  BN_free(f->x.k);
+
+  free(f);
+}
+
+
+/**
+ * \brief Initialized a continued fraction.
+ *
+ * A continued fraction for a floating number x can be expressed as a series
+ *  <a₀; a₁, a₂…, aₙ>
+ * such that
+ * <pre>
+ *
+ *                1
+ *  x = a₀ + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
+ *                    1
+ *           a₁ + ⎽⎽⎽⎽⎽⎽⎽⎽⎽
+ *                 a₂ + …
+ *
+ * </pre>
+ * , where for each i < n, there exists an approximation hᵢ / kᵢ.
+ * By definition,
+ *   a₋₁ = 0
+ *   h₋₁ = 1    h₋₂ = 0
+ *   k₋₁ = 0    k₋₂ = 1
+ *
+ * \param f     A continued fraction structure. If f is NULL, a new one is
+ *              allocated.
+ * \param num   Numerator to be used as initial numerator for the fraction to be
+ *              approximated.
+ * \param den   Denominator to be used as denominator for the fraction to be
+ *              approximated.
+ *
+ * \return the continued fraction fiven as input.
+ */
+cf_t* cf_init(cf_t* f, BIGNUM* num, BIGNUM* den)
+{
+  if (!f) f = cf_new();
+
+  BN_zero(f->fs[0].h);
+  BN_one(f->fs[0].k);
+
+  BN_one(f->fs[1].h);
+  BN_zero(f->fs[1].k);
+
+  f->i = 2;
+  if (!BN_copy(f->x.h, num)) return NULL;
+  if (!BN_copy(f->x.k, den)) return NULL;
+
+  return f;
+}
+
+
+/**
+ * \brief Produces the next fraction.
+ *
+ * Each new approximation hᵢ/kᵢ is defined rec ursively as:
+ *   hᵢ = aᵢhᵢ₋₁ + hᵢ₋₂
+ *   kᵢ = aᵢkᵢ₋₁ + kᵢ₋₂
+ * Meanwhile each new aᵢ is simply the integer part of x.
+ *
+ *
+ * \param f   The continued fraction.
+ * \return NULL if the previous fraction approximates at its best the number,
+ *         a pointer to the next fraction in the series othw.
+ */
+bigfraction_t* cf_next(cf_t *f)
+{
+  bigfraction_t *ith_fs = &f->fs[f->i];
+  BIGNUM* rem = BN_new();
+
+  if (BN_is_zero(f->x.h)) return NULL;
+  BN_div(f->a, rem, f->x.h, f->x.k, f->ctx);
+
+  /* computing hᵢ */
+  BN_mul(f->fs[f->i].h , f->a, f->fs[(f->i-1+3) % 3].h, f->ctx);
+  BN_uadd(f->fs[f->i].h, f->fs[f->i].h, f->fs[(f->i-2+3) % 3].h);
+  /* computing kᵢ */
+  BN_mul(f->fs[f->i].k , f->a, f->fs[(f->i-1+3) % 3].k, f->ctx);
+  BN_uadd(f->fs[f->i].k, f->fs[f->i].k, f->fs[(f->i-2+3) % 3].k);
+
+  f->i = (f->i + 1) % 3;
+  /* update x. */
+  BN_copy(f->x.h, f->x.k);
+  BN_copy(f->x.k, rem);
+
+  return ith_fs;
+}
 
 /*
  *  Weiner Attack Implementation