void merge(T a[], n_t n) { for (n_t n_sub(1); n_sub < n; n_sub *= 2) for (index_t i(0); i < n; i += n_sub * 2) { // Merge a[i..i+n_sub) and a[i+n_sub..i+n_sub*2) to a[i..i+n_sub*2) T* const begin(a + i); T* const middle(a + std::min(n, i + n_sub)); T* const end(a + std::min(n, i + n_sub * 2)); std::inplace_merge(begin, middle, end, begin); } }
static void nm_exp( DH_NUMBERS *x, DH_NUMBERS *n, DH_NUMBERS *z ) { DH_NUMBERS xt, nt; nm_assign( &nt, n ); nm_assign( &xt, x ); nm_assign( z, &NUMBERS_ONE ); while (nt.length) { while ( ! (nt.values[0] & 1) ) { nm_mult( &xt, &xt, &xt ); nm_div2( &nt ); } nm_mult( &xt, z, z ); nt.length = n_sub( nt.values, NUMBERS_ONE.values, nt.values, nt.length, NUMBERS_ONE.length ); } }
static void n_div( DH_NUMBERS *d1, DH_NUMBERS *z2, DH_NUMBERS *q, DH_NUMBERS *r ) { static DH_NUMBERS dummy_rest; static DH_NUMBERS dummy_quot; uint16_t *i1, *i1e, *i3; int l2, ld, l, lq; #if MAXINT != 1 uint16_t z; int pw, l2t; #endif if (!z2->length) // abort(); return; if (!r) r = &dummy_rest; if (!q) q = &dummy_quot; nm_assign( r, d1 ); l2 = z2->length; l = r->length - l2; lq = l + 1; i3 = q->values + l; i1 = r->values + l; ld = l2; i1e = i1 + (ld - 1); for (; l >= 0; ld++, i1--, i1e--, l--, i3--) { *i3 = 0; if (ld == l2 && ! *i1e) { ld--; continue; } if ( ld > l2 || (ld == l2 && n_cmp( i1, z2->values, l2) >= 0 ) ) { #if MAXINT != 1 for (pw = MAXBIT - 1, z = (uint16_t)HIGHBIT; pw >= 0; pw--, z /= 2) { if ( ld > (l2t = z2[pw].length) || (ld == l2t && n_cmp( i1, z2[pw].values, ld) >= 0) ) { ld = n_sub( i1, z2[pw].values, i1, ld, l2t ); (*i3) += z; } } #else ld = n_sub( i1, z2->values, i1, ld, l2 ); (*i3) ++; #endif } } l ++; lq -= l; ld += l; if (lq > 0 && !q->values[lq - 1]) lq--; q->length = lq; r->length = ld - 1; }