Browse Source

decaf double and double-scalarmul, but needs to be tested

master
Michael Hamburg 10 years ago
parent
commit
06be9ef253
3 changed files with 85 additions and 5 deletions
  1. +32
    -0
      include/decaf.h
  2. +46
    -5
      src/decaf.c
  3. +7
    -0
      test/bench.c

+ 32
- 0
include/decaf.h View File

@@ -28,6 +28,7 @@
#define NONNULL1 __attribute__((nonnull(1))) #define NONNULL1 __attribute__((nonnull(1)))
#define NONNULL2 __attribute__((nonnull(1,2))) #define NONNULL2 __attribute__((nonnull(1,2)))
#define NONNULL3 __attribute__((nonnull(1,2,3))) #define NONNULL3 __attribute__((nonnull(1,2,3)))
#define NONNULL5 __attribute__((nonnull(1,2,3,4,5)))


/** Types of internal words. TODO: ARCH: make 32-bit clean */ /** Types of internal words. TODO: ARCH: make 32-bit clean */
typedef uint64_t decaf_word_t, decaf_bool_t; typedef uint64_t decaf_word_t, decaf_bool_t;
@@ -236,6 +237,18 @@ void decaf_point_add (
const decaf_point_t b const decaf_point_t b
) API_VIS NONNULL3; ) API_VIS NONNULL3;


/**
* @brief Double a point. Equivalent to
* decaf_point_add(two_a,a,a), but potentially faster.
*
* @param [out] sum The sum a+a.
* @param [in] a A point.
*/
void decaf_point_double (
decaf_point_t two_a,
const decaf_point_t a
) API_VIS NONNULL2;

/** /**
* @brief Subtract two points to produce a third point. The * @brief Subtract two points to produce a third point. The
* input points and output point can be pointers to the same * input points and output point can be pointers to the same
@@ -264,6 +277,24 @@ void decaf_point_scalarmul (
const decaf_scalar_t scalar const decaf_scalar_t scalar
) API_VIS NONNULL3; ) API_VIS NONNULL3;


/**
* @brief Multiply two base points by two scalars.
*
* @param [out] scaled The scaled point base*scalar
* @param [in] base1 A first point to be scaled.
* @param [in] scalar1 A first scalar to multilpy by.
* @param [in] base2 A second point to be scaled.
* @param [in] scalar2 A second scalar to multilpy by.
* @TODO: test
*/
void decaf_point_double_scalarmul (
decaf_point_t combo,
const decaf_point_t base1,
const decaf_scalar_t scalar1,
const decaf_point_t base2,
const decaf_scalar_t scalar2
) API_VIS NONNULL5;

/** /**
* @brief Test that a point is valid, for debugging purposes. * @brief Test that a point is valid, for debugging purposes.
* *
@@ -327,6 +358,7 @@ void decaf_point_from_hash_uniform (
#undef NONNULL1 #undef NONNULL1
#undef NONNULL2 #undef NONNULL2
#undef NONNULL3 #undef NONNULL3
#undef NONNULL5


#ifdef __cplusplus #ifdef __cplusplus
}; /* extern "C" */ }; /* extern "C" */


+ 46
- 5
src/decaf.c View File

@@ -463,8 +463,10 @@ void decaf_point_add(decaf_point_t a, const decaf_point_t b, const decaf_point_t
decaf_point_add_sub(a,b,c,0); decaf_point_add_sub(a,b,c,0);
} }


/* No dedicated point double (PERF) */
#define decaf_dbl(a,b) decaf_point_add(a,b,b)
/* No dedicated point double yet (PERF) */
void decaf_point_double(decaf_point_t a, const decaf_point_t b) {
decaf_point_add(a,b,b);
}


void decaf_copy ( void decaf_copy (
decaf_point_t a, decaf_point_t a,
@@ -522,16 +524,16 @@ void decaf_point_scalarmul (
* possibly-odd number of unmasked bits, may need to mask. * possibly-odd number of unmasked bits, may need to mask.
*/ */
decaf_point_t w,b3,tmp; decaf_point_t w,b3,tmp;
decaf_dbl(w,b);
decaf_point_double(w,b);
/* b3 = b*3 */ /* b3 = b*3 */
decaf_point_add(b3,w,b); decaf_point_add(b3,w,b);
int i; int i;
for (i=DECAF_SCALAR_LIMBS*WBITS-2; i>0; i-=2) { for (i=DECAF_SCALAR_LIMBS*WBITS-2; i>0; i-=2) {
decaf_word_t bits = scalar->limb[i/WBITS]>>(i%WBITS); decaf_word_t bits = scalar->limb[i/WBITS]>>(i%WBITS);
decaf_cond_sel(tmp,b,b3,((bits^(bits>>1))&1)-1); decaf_cond_sel(tmp,b,b3,((bits^(bits>>1))&1)-1);
decaf_dbl(w,w);
decaf_point_double(w,w);
decaf_point_add_sub(w,w,tmp,((bits>>1)&1)-1); decaf_point_add_sub(w,w,tmp,((bits>>1)&1)-1);
decaf_dbl(w,w);
decaf_point_double(w,w);
} }
decaf_point_add_sub(w,w,b,((scalar->limb[0]>>1)&1)-1); decaf_point_add_sub(w,w,b,((scalar->limb[0]>>1)&1)-1);
/* low bit is special because fo signed window */ /* low bit is special because fo signed window */
@@ -539,6 +541,45 @@ void decaf_point_scalarmul (
decaf_point_sub(a,w,tmp); decaf_point_sub(a,w,tmp);
} }


void decaf_point_double_scalarmul (
decaf_point_t a,
const decaf_point_t b,
const decaf_scalar_t scalarb,
const decaf_point_t c,
const decaf_scalar_t scalarc
) {
/* w=2 signed window uses about 1.5 adds per bit.
* I figured a few extra lines was worth the 25% speedup.
* NB: if adapting this function to scalarmul by a
* possibly-odd number of unmasked bits, may need to mask.
*/
decaf_point_t w,b3,c3,tmp;
decaf_point_double(w,b);
decaf_point_double(tmp,c);
/* b3 = b*3 */
decaf_point_add(b3,w,b);
decaf_point_add(c3,tmp,c);
decaf_point_add(w,w,tmp);
int i;
for (i=DECAF_SCALAR_LIMBS*WBITS-2; i>0; i-=2) {
decaf_point_double(w,w);
decaf_word_t bits = scalarb->limb[i/WBITS]>>(i%WBITS);
decaf_cond_sel(tmp,b,b3,((bits^(bits>>1))&1)-1);
decaf_point_add_sub(w,w,tmp,((bits>>1)&1)-1);
bits = scalarc->limb[i/WBITS]>>(i%WBITS);
decaf_cond_sel(tmp,c,c3,((bits^(bits>>1))&1)-1);
decaf_point_add_sub(w,w,tmp,((bits>>1)&1)-1);
decaf_point_double(w,w);
}
decaf_point_add_sub(w,w,b,((scalarb->limb[0]>>1)&1)-1);
decaf_point_add_sub(w,w,c,((scalarc->limb[0]>>1)&1)-1);
/* low bit is special because of signed window */
decaf_cond_sel(tmp,b,decaf_point_identity,-(scalarb->limb[0]&1));
decaf_point_sub(w,w,tmp);
decaf_cond_sel(tmp,c,decaf_point_identity,-(scalarc->limb[0]&1));
decaf_point_sub(a,w,tmp);
}

decaf_bool_t decaf_point_eq ( const decaf_point_t p, const decaf_point_t q ) { decaf_bool_t decaf_point_eq ( const decaf_point_t p, const decaf_point_t q ) {
/* equality mod 2-torsion compares x/y */ /* equality mod 2-torsion compares x/y */
gf a, b; gf a, b;


+ 7
- 0
test/bench.c View File

@@ -372,6 +372,13 @@ int main(int argc, char **argv) {
} }
when = now() - when; when = now() - when;
printf("decaf slow: %5.1fµs\n", when * 1e6 / i); printf("decaf slow: %5.1fµs\n", when * 1e6 / i);
when = now();
for (i=0; i<nbase/10; i++) {
decaf_point_double_scalarmul(Da,Db,bsc,Dc,asc);
}
when = now() - when;
printf("decaf slo2: %5.1fµs\n", when * 1e6 / i);


when = now(); when = now();
for (i=0; i<nbase/10; i++) { for (i=0; i<nbase/10; i++) {


Loading…
Cancel
Save