Пример #1
0
static int base58_decode(mrb_state *mrb, char *dst, const char *data, int length, const char *chars)
{
  int leading_zero = 0;
  int i;
  Bignum *result = bignum_alloc_char(mrb, 0);
  Bignum *base = bignum_alloc_char(mrb, 1);
  int b_length;

  for (i = 0; i < length; ++i) {
    if (data[i] == chars[0]) {
      leading_zero++;
    }
    else {
      break;
    }
  }
  
  memset(dst, 0, leading_zero);
  
  for (i = length - 1; i > leading_zero - 1; --i) {
    
    Bignum *f = bignum_alloc_char(mrb, 0);
    int j, c = -1;
    
    for (j = 0; j < 58; ++j) {
      if (data[i] == chars[j]) {
        c = j;
        break;
      }
    }
    
    if (c == -1) return -1;
    
    for (j = 0; j < c; ++j) bignum_add(result, base);
    for (j = 0; j < 58; ++j) bignum_add(f, base);
    
    bignum_free(base);
    base = f;
  }
  
  bignum_free(base);
  
  b_length = bignum_length(result);
  memcpy(dst + leading_zero, result->data + result->len - b_length , b_length);
  bignum_free(result);
  
  return leading_zero + b_length;
}
Пример #2
0
bignum* bignum_sub(bignum a, bignum b) {
    b.sign = !b.sign;

    bignum* sum = bignum_add(a, b);

    return sum;
}
Пример #3
0
main(int argc, char** argv)
{
	char bignum_1[1000];
	char bignum_2[1000];
	int i, j = 0, k = 0;

	zero(bignum_1, 1000);
	zero(bignum_2, 1000);

	bignum_1[999] = 1;

	printf("NOTE: there's a limit of 1000 digits\n");
	printf("calculate factorial of: ");
	scanf("%d", &i);

	while(i--){
		/* memcpy(bignum_2, bignum_1, 1000); */
		wannabe_memcpy(bignum_2, bignum_1, 1000);
		for(j = i; j>0; j--)
			bignum_add(bignum_1, bignum_2);
	}

	bignum_put(bignum_1);
	return 0;
}
Пример #4
0
Файл: bignum.c Проект: rtfb/82k
void bignum_init_base_convert(size_t size, int base) {
    bignum multiplier;
    bignum_init(&multiplier);
    bignum_from_int(&multiplier, 1);
    mul_lut = malloc(size * sizeof(bignum));
    mul_lut_size = size;
    for (int i = 0; i < size; ++i) {
        bignum_init(&mul_lut[i]);
        bignum_copy(&mul_lut[i], &multiplier);
        bignum_mul_int(&multiplier, base);
    }
    bignum_free(&multiplier);

    bignum sum;
    bignum_init(&sum);
    for (int i = 0; i < SUMSZ; ++i) {
        for (int j = 0; j < 256; ++j) {
            int m = i*8;
            bignum_from_int(&sum, 0);
            for (uint8_t mask = 1; mask != 0; mask <<= 1) {
                if (j & mask) {
                    bignum_add(&sum, &mul_lut[m]);
                }
                ++m;
            }
            bignum_init(&sum_lut[i][j]);
            bignum_copy(&sum_lut[i][j], &sum);
        }
    }
    bignum_free(&sum);
}
Пример #5
0
Файл: 025.c Проект: n5c/euler
int find_nth_first_nbits_fibonacci(int nbits)
{
	int i, nth, idx;
	struct bignum num[2] = {0};

	nth = 3;
	num[0].d[0] = 1;
	num[1].d[0] = 1;
	while (1) {
		idx = ((nth & 0x1) ^ 0x1);
		bignum_add(&num[idx], &num[(idx ^ 0x1)]);
		if (((num[idx].used + 1) * 5) >= nbits) {
			int tmp = ((num[idx].used + 1) * 5);
			for (i = 10000; i > 0; i /= 10) {
				if (num[idx].d[num[idx].used] / i == 0)
					tmp--;
			}
			if (tmp >= nbits)
				break;
		}
		nth++;
	}

	return nth;
}
Пример #6
0
void comb_fast_sum(bignum_t* sum, const byte* comb_set)
{
    int i;
    bignum_copy(sum, &all_sums_by_word_and_pos[0][*(uint16_t*)comb_set]);
    for (i = 1; i < 5; i++)
        bignum_add(sum, &all_sums_by_word_and_pos[i][((uint16_t*)comb_set)[i]]);
}
Пример #7
0
void comb_sum(bignum_t* sum, const byte* comb_set)
{
    int i;
    bignum_clear(sum);
    for (i = 0; i < 70; i++)
        if (comb_set[i / 8] & (1 << (i % 8)))
            bignum_add(sum, &nums[i]);
}
Пример #8
0
Файл: bignum.c Проект: rtfb/82k
/*
Examples:
82000 (base 3) = 11011111001 =
1*3**0 + 0*3**1 + 0*3**2 + 1*3**3 +3**4 +3**5 +3**6 +3**7 +0*3**8 +3**9 +3**10

82000 (base 5) = 10111000 =
0*5**0 + 0*5**1 + 0*5**2 + 1*5**3 + 1*5**4 + 1*5**5 + 0*5**6 + 1*5**7
*/
void bignum_from_string_binary(bignum *n, char const* s, size_t base) {
    char const *end_of_s = s + strlen(s) - 1;
    bignum_from_int(n, 0);
    bignum multiplier;
    bignum_init(&multiplier);
    bignum_from_int(&multiplier, 1);
    while (end_of_s != s) {
        assert((*end_of_s == '1') || (*end_of_s == '0'));
        if (*end_of_s == '1') {
            bignum_add(n, &multiplier);
        }
        bignum_mul_int(&multiplier, base);
        --end_of_s;
    }
    bignum_add(n, &multiplier);
    bignum_free(&multiplier);
}
Пример #9
0
Bool bignum_div3(BigNum b1, BigNum b2, BigNum *b3, BigNum *b4)
{
  //----  局所宣言
  BigNum low;    // 下端
  BigNum hig;    // 上端
  BigNum mid;    // 中央
  BigNum val;     // 計算値(除数と仮整商の積)
  BigNum t;      // 一時変数
  int sft;       // 上端の節数
  int cmp;       // 大小比較の結果

  //----  事前処理
  // 除数の吟味(0除算の禁止)
  if ( bignum_zero(b2) == TRUE ) { return FALSE; }

  //----  初期処理
  bignum_init(&low, 0);       // 下端の初期化(0)
  bignum_init(&hig, 1);       // 上端の仮値(1)
  sft = b1.uni-b2.uni+1;   // 上端の節数
  bignum_shift(&hig, sft);    // 上端の初期化(節移動)
  //----  計算処理
  //--  整商の計算
  while ( bignum_near(low, hig, 1) == 0 ) {
    //   上端と下端の中点として中央値をmidに格納
    bignum_add(low, hig, &mid);

    bignum_half(&mid);
    //   中央値midとb2の乗算をvalに格納l
    if ( bignum_mlt(mid, b2, &val) == FALSE ) {
      return FALSE;
    }
    //   b1とvalが等しければ脱出
    cmp = bignum_cmp(val, b1);
    if ( cmp == 0 ) {
      low = mid;
      break;
    }
    //   異なれば上端または下端を更新
    else if ( cmp > 0 ) {
      hig = mid;
    } else {
      low = mid;
    }
  }
  //--  整商の格納と剰余の計算
  // 下端値lowを整商*b3として格納
  *b3 = low;
  // 整商*b3とb2の乗算をvalに格納l
  bignum_mlt(*b3, b2, &val);
  // b1とvalの差を剰余として*b4に格納
  bignum_sub(b1, val, b4);
  //----  事後処理
  bignum_chk(b3);    // 節数の更新
  bignum_chk(b4);

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Пример #10
0
bignum* bignum_add(bignum a, bignum b) {
    char carry = 0;

    /* Indique l'opération à  faire en valeur absolue
       1 si les deux nombres sont additionnés en valeur absolue
       -1 s'il s'agit d'une soustraction
    */
    char op = 1;

    int i = 0;
    int size_a = bignum_len(a), size_b = bignum_len(b), max_size = MAX(size_a, size_b);

    bignum* sum = bignum_init();

    bigdigit* digit = NULL;
    bigdigit** da = &a.first;
    bigdigit** db = &b.first;
    bigdigit** next = &sum->first;

    if(a.sign == b.sign) {
        sum->sign = a.sign;
    } else {
        // Assure que |a| >= |b| par la suite
        if(bignum_absgt(b, a)) {
            bignum_destoroyah(sum);
            return bignum_add(b, a);
        }

        sum->sign = a.sign;
        op = -1;
    }

    for(i = 0; i < max_size + 1; i++) {
        digit = bigdigit_init();

        digit->value = carry;

        if(i < size_a) {
            digit->value += (*da)->value;
            da = &(*da)->next;
        }
        if(i < size_b) {
            digit->value += op * (*db)->value;
            db = &(*db)->next;
        }

        carry = op * (digit->value >= 10 || digit->value < 0);
        digit->value = (digit->value + 10) % 10;
        *next = digit;
        next = &digit->next;
    }

    *next = NULL;
    bignum_clean(sum);

    return sum;
}
Пример #11
0
bignum_t * bignum_add_to_ (bignum_t * a, bignum_t * b, bool clear_flag) {
	bignum_t * c = bignum_add (a, b);

	bignum_delete (a);

	if (clear_flag)
		bignum_delete (b);

	return c;
}
Пример #12
0
Файл: bignum.c Проект: rtfb/82k
// a *= b
void bignum_mul_int_silly_loop(bignum *a, unsigned int b) {
    bignum tmp;
    bignum_init(&tmp);
    bignum_copy(&tmp, a);
    --b;
    // XXX: this loop is probably quite inefficient, think of something better
    while (b > 0) {
        bignum_add(a, &tmp);
        --b;
    }
    bignum_free(&tmp);
}
Пример #13
0
bignum* bignum_dumb_mul(bignum a, bignum b) {
    // Optimisation
    if(bignum_absgt(b, a))
        return bignum_dumb_mul(b, a);

    bignum* prod = bignum_fromstr("0");
    bignum* zero = bignum_fromstr("0");
    bignum* dec = bignum_fromstr("-1");

    char sign = a.sign != b.sign;

    bignum* b_copy = bignum_copy(&b);
    b_copy->sign = 0;
    bignum* add_result = NULL;
    bignum* prod_result = NULL;

    a.sign = 0;

    while(!bignum_eq(*b_copy, *zero)) {
        add_result = bignum_add(*b_copy, *dec);
        bignum_destoroyah(b_copy);
        b_copy = add_result;

        prod_result = bignum_add(*prod, a);
        bignum_destoroyah(prod);
        prod = prod_result;
    }

    bignum_destoroyah(b_copy);
    bignum_destoroyah(zero);
    bignum_destoroyah(dec);

    prod->sign = sign;

    return prod;
}
Пример #14
0
Bool bignum_sqrt(BigNum b1, BigNum *b0)
{
  //----  局所宣言
  BigNum low;    // 下端
  BigNum hig;    // 上端
  BigNum mid;    // 中央
  BigNum val;    // 二乗値
  int sft;       // 上端の節数
  int cmp;       // 大小比較の結果

  //----  初期処理
  // lowを最下端0に初期化
  bignum_init(&low, 0);
  // higを最上端に初期化
  // 最上端は結果が含まれる範囲でキリの良い値
  // 1で初期化し、適当な節だけ左シフト
  sft = (UNI-1)/2;
  bignum_init(&hig, 1);
  bignum_shift(&hig, sft);
  //----  計算処理
  while ( bignum_near(hig, low, 1) == FALSE ) {
    //   上端と下端の中点として中央値midの計算
    bignum_add(low, hig, &mid);
    bignum_half(&mid);
    //   中央値midの二乗値val
    bignum_mlt(mid, mid, &val);
    //   二乗値valが入力値b1と等しければ脱出
    cmp = bignum_cmp(val, b1);
    if ( cmp == 0 ) {
      break;
    }//   異なれば上端または下端を更新
    else if ( cmp > 0 ) {
      hig = mid;
    } else {
      low = mid;
    }
  }

  //----  事後処理
  // 中央値midを結果b0に格納
  *b0 = mid;
  // 節数と桁数の更新
  bignum_chk(b0);
  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Пример #15
0
int bignum_is_lychrel(const bignum *a, int tries) {
    bignum *b, *c;
    int i, result = 1;

    b = bignum_copy(a);
    for (i = 0; i < tries; i++) {
        c = bignum_copy(b);
        bignum_reverse_digits(b);
        bignum_add(b, c);
        bignum_delete(c);
        if (bignum_is_palindrome(b)) {
            result = 0;
            break;
        }
    }
    bignum_delete(b);
    return result;
}
Пример #16
0
Файл: 10334.c Проект: treblih/oj
int main(int argc, const char *argv[])
{
#ifdef DB
	fp = fopen("input", "r");
#endif
	int i, idx;
	int digits = 1;
	fibo[0].arr[0] = 1;
	fibo[1].arr[0] = 2;
	for (i = 2; i <= 5000; ++i) {
		digits = bignum_add(i, digits);
	}
	while (scanf("%d", &idx) != EOF) {
		if (!idx) {puts("1"); continue;}
		bignum_print(idx);
		putchar('\n');
	}
	return 0;
}
Пример #17
0
Bool bignum_div4(BigNum b1, BigNum b2, BigNum *b3, BigNum *b4)
{
  //----  局所宣言
  int uni;     // 節数の差
  BigNum t, p;    // 一時変数
  int a;       // 各節の整商
  int k;       // 反復変数

  //----  事前処理
  // 除数の吟味(0除算の禁止)
  if ( bignum_zero(b2) == TRUE ) { return FALSE; }

  //----  初期処理
  bignum_init(b3, 0);                  // 整商の初期化(0)
  bignum_init(b4, 0);                  // 剰余の初期化(0)
  uni = b1.uni - b2.uni +1;            // 節数の差(整商の節数)

  //----  計算処理
  for ( k = uni; k >= 0; k-- ) {
    bignum_scl(b4, RAD);
    bignum_add(b1, *b4, &t);
    b1 = t;

    b2 = t;
    bignum_shift(&t, k);
    bignum_output(b1);
    bignum_output(t);
    bignum_div1(b1, t, &a, b4);
    bignum_scl(&t, a);
    bignum_sub(b1, t, &p);
    b1 = p;
    b3->num[k] = a;
  }

  //----  事後処理
  bignum_chk(b3);
  bignum_chk(b4);

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Пример #18
0
Bool bignum_plrt(BigNum b1, int e, BigNum *b0)
{
  //----  局所宣言
  BigNum low;    // 下端
  BigNum hig;    // 上端
  BigNum mid;    // 中央
  BigNum val;    // 累乗値
  int sft;       // 上端の節数
  int cmp;       // 大小比較の結果

  //----  初期処理
  bignum_init(&low, 0);
  bignum_init(&hig, 1);
  sft = (UNI-1)/e;
  bignum_shift(&hig, sft);

  //----  計算処理
  while ( bignum_near(low, hig, 1) == 0 ) {
    bignum_add(low, hig, &mid);
    bignum_half(&mid);

    bignum_pow(mid, e, &val);
    cmp = bignum_cmp(val, b1);
    if ( cmp == 0 ) {
      break;
    } else if ( cmp > 0 ) {
      hig = mid;
    } else {
      low = mid;
    }
  }

  //----  事後処理
  *b0 = mid;
  bignum_chk(b0);

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Пример #19
0
static
int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
{

	struct sockaddr_storage tmp, mask, network, rnd;
	unsigned i, max_loops = MAX_IP_TRIES;
	int ret;
	const char* c_network, *c_netmask;
	char buf[64];

	if (proc->config.ipv6_network && proc->config.ipv6_netmask) {
		c_network = proc->config.ipv6_network;
		c_netmask = proc->config.ipv6_netmask;
	} else {
		c_network = s->config->network.ipv6;
		c_netmask = s->config->network.ipv6_netmask;
	}

	if (c_network && c_netmask) {
		ret =
		    inet_pton(AF_INET6, c_network, SA_IN6_P(&network));

		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
			return -1;
		}

		ret =
		    inet_pton(AF_INET6, c_netmask, SA_IN6_P(&mask));
	
		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
			return -1;
		}
		
		proc->ipv6 = calloc(1, sizeof(*proc->ipv6));
		if (proc->ipv6 == NULL)
			return ERR_MEM;

		/* mask the network */
		for (i=0;i<sizeof(struct in6_addr);i++)
			SA_IN6_U8_P(&network)[i] &= (SA_IN6_U8_P(&mask)[i]);
		((struct sockaddr_in6*)&network)->sin6_family = AF_INET6;
		((struct sockaddr_in6*)&network)->sin6_port = 0;

       		memcpy(&tmp, &network, sizeof(tmp));
        	((struct sockaddr_in6*)&tmp)->sin6_family = AF_INET6;
        	((struct sockaddr_in6*)&tmp)->sin6_port = AF_INET6;

        	((struct sockaddr_in6*)&rnd)->sin6_family = AF_INET6;
        	((struct sockaddr_in6*)&rnd)->sin6_port = AF_INET6;

		do {
			if (max_loops == 0) {
				mslog(s, NULL, LOG_ERR, "could not figure out a valid IPv6 IP.");
				ret = ERR_NO_IP;
				goto fail;
			}
			
			if (max_loops == MAX_IP_TRIES) {
				uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
				memset(SA_IN6_U8_P(&rnd), 0, sizeof(struct in6_addr));
				memcpy(SA_IN6_U8_P(&rnd)+sizeof(struct in6_addr)-5, &t, 4);
			} else
				gnutls_rnd(GNUTLS_RND_NONCE, SA_IN6_U8_P(&rnd), sizeof(struct in6_addr));
			max_loops--;
			
			/* Mask the random number with the netmask */
        		for (i=0;i<sizeof(struct in6_addr);i++)
        			SA_IN6_U8_P(&rnd)[i] &= ~(SA_IN6_U8_P(&mask)[i]);

			SA_IN6_U8_P(&rnd)[sizeof(struct in6_addr)-1] &= 0xFE;

			/* Now add the network to the masked random number */
        		for (i=0;i<sizeof(struct in6_addr);i++)
        			SA_IN6_U8_P(&rnd)[i] |= (SA_IN6_U8_P(&network)[i]);
        			
 			/* check if it exists in the hash table */
			if (ip_lease_exists(s, &rnd, sizeof(struct sockaddr_in6)) != 0) {
				mslog(s, proc, LOG_DEBUG, "cannot assign local IP %s to '%s'; it is in use.", 
				      human_addr((void*)&rnd, sizeof(struct sockaddr_in6), buf, sizeof(buf)), 
				      proc->username);
				continue;
			}

        		proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
        		memcpy(&proc->ipv6->lip, &rnd, proc->ipv6->lip_len);

        		/* RIP = LIP + 1 */
        		memcpy(&tmp, &proc->ipv6->lip, proc->ipv6->rip_len);

	        	bignum_add(SA_IN6_U8_P(&tmp), sizeof(struct in6_addr), 1);

 			/* check if it exists in the hash table */
			if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in6)) != 0) {
				mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.", 
				      human_addr((void*)&tmp, sizeof(struct sockaddr_in6), buf, sizeof(buf)), 
				      proc->username);
				continue;
			}

        		proc->ipv6->rip_len = sizeof(struct sockaddr_in6);
        		memcpy(&proc->ipv6->rip, &tmp, proc->ipv6->rip_len);

        		/* mask the last IP with the netmask */
        		for (i=0;i<sizeof(struct in6_addr);i++)
	        		SA_IN6_U8_P(&tmp)[i] &= (SA_IN6_U8_P(&mask)[i]);

        		/* the result should match the network */
	        	if (memcmp(SA_IN6_U8_P(&network), SA_IN6_U8_P(&tmp), sizeof(struct in6_addr)) != 0) {
		        	continue;
	        	}

			mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s", proc->username,
			      human_addr((void*)&proc->ipv6->lip, proc->ipv6->lip_len, buf, sizeof(buf)));

	        	if (icmp_ping6(s, (void*)&proc->ipv6->lip, (void*)&proc->ipv6->rip) == 0)
	        		break;
                } while(1);
	}

	return 0;
fail:
	free(proc->ipv6);
	proc->ipv6 = NULL;

	return ret;

}
Пример #20
0
Файл: bignum.c Проект: rtfb/82k
// assign n from s, treat s as being in base 'base'
void bignum_base_convert(bignum *n, bignum* s) {
    bignum_from_int(n, 0);
    for (int i = 0; i < s->size; ++i) {
        bignum_add(n, &sum_lut[i][s->data[i]]);
    }
}
Пример #21
0
/**
 * crypto_rsa_exptmod - RSA modular exponentiation
 * @in: Input data
 * @inlen: Input data length
 * @out: Buffer for output data
 * @outlen: Maximum size of the output buffer and used size on success
 * @key: RSA key
 * @use_private: 1 = Use RSA private key, 0 = Use RSA public key
 * Returns: 0 on success, -1 on failure
 */
int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen,
		       struct crypto_rsa_key *key, int use_private)
{
	struct bignum *tmp, *a = NULL, *b = NULL;
	int ret = -1;
	size_t modlen;

	if (use_private && !key->private_key)
		return -1;

	tmp = bignum_init();
	if (tmp == NULL)
		return -1;

	if (bignum_set_unsigned_bin(tmp, in, inlen) < 0)
		goto error;
	if (bignum_cmp(key->n, tmp) < 0) {
		/* Too large input value for the RSA key modulus */
		goto error;
	}

	if (use_private) {
		/*
		 * Decrypt (or sign) using Chinese remainer theorem to speed
		 * up calculation. This is equivalent to tmp = tmp^d mod n
		 * (which would require more CPU to calculate directly).
		 *
		 * dmp1 = (1/e) mod (p-1)
		 * dmq1 = (1/e) mod (q-1)
		 * iqmp = (1/q) mod p, where p > q
		 * m1 = c^dmp1 mod p
		 * m2 = c^dmq1 mod q
		 * h = q^-1 (m1 - m2) mod p
		 * m = m2 + hq
		 */
		a = bignum_init();
		b = bignum_init();
		if (a == NULL || b == NULL)
			goto error;

		/* a = tmp^dmp1 mod p */
		if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0)
			goto error;

		/* b = tmp^dmq1 mod q */
		if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0)
			goto error;

		/* tmp = (a - b) * (1/q mod p) (mod p) */
		if (bignum_sub(a, b, tmp) < 0 ||
		    bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0)
			goto error;

		/* tmp = b + q * tmp */
		if (bignum_mul(tmp, key->q, tmp) < 0 ||
		    bignum_add(tmp, b, tmp) < 0)
			goto error;
	} else {
		/* Encrypt (or verify signature) */
		/* tmp = tmp^e mod N */
		if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0)
			goto error;
	}

	modlen = crypto_rsa_get_modulus_len(key);
	if (modlen > *outlen) {
		*outlen = modlen;
		goto error;
	}

	if (bignum_get_unsigned_bin_len(tmp) > modlen)
		goto error; /* should never happen */

	*outlen = modlen;
	os_memset(out, 0, modlen);
	if (bignum_get_unsigned_bin(
		    tmp, out +
		    (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0)
		goto error;

	ret = 0;

error:
	bignum_deinit(tmp);
	bignum_deinit(a);
	bignum_deinit(b);
	return ret;
}
Пример #22
0
/**
 * Algo de karatsuba pour la multiplication de grands entiers
 */
bignum* bignum_mul(bignum a, bignum b) {
    int len_a = bignum_len(a);
    int len_b = bignum_len(b);

    // Multiplication stupide pour les petits nombres
    if(len_a < 2 || len_b < 2) {
        return bignum_dumb_mul(a, b);
    }
    int max = MAX(len_a, len_b);
    int max_middle = max/2;

    bignum* high_a = bignum_init();
    bignum* high_b = bignum_init();
    bignum* low_a = bignum_init();
    bignum* low_b = bignum_init();

    bignum_split(a, max-max_middle, high_a, low_a);
    bignum_split(b, max-max_middle, high_b, low_b);

    bignum* z2 = bignum_mul(*high_a, *high_b);
    bignum* z0 = bignum_mul(*low_a, *low_b);

    // Je voudrais de l'operator overloading : (z2*10^(max))+((z1-z2-z0)*10^(max_middle))+(z0)
    bignum* sum_a = bignum_add(*low_a, *high_a);
    bignum* sum_b = bignum_add(*low_b, *high_b);

    bignum_destoroyah(high_a);
    bignum_destoroyah(high_b);
    bignum_destoroyah(low_a);
    bignum_destoroyah(low_b);

    // z1 = (sum_a*sum_b) - z2 - z0
    bignum* mul_of_sum = bignum_mul(*sum_a, *sum_b);
    bignum* diff_a = bignum_sub(*mul_of_sum,*z2);
    bignum* z1 = bignum_sub(*diff_a, *z0);

    bignum_destoroyah(mul_of_sum);
    bignum_destoroyah(diff_a);
    bignum_destoroyah(sum_a);
    bignum_destoroyah(sum_b);

    //arrondir pour avoir la bonne puissance de 10 dans les shifts.
    float inter = (float)max;
    inter = inter/2.0f;
    inter += 0.5f;
    max_middle = (int) inter;
    if(max%2 == 1){
        max++;
    }

    //r1 = z2*10^(max)
    bignum* r1 = bignum_copy(z2);
    bignum_shift_left(r1, max);

    //r2 = z1
    bignum* r2 = bignum_copy(z1);
    //r2 = r2*10^(max_middle)
    bignum_shift_left(r2, max_middle);
    //r3 = r2 + z0
    bignum* r3 = bignum_add(*r2, *z0);

    //bignum_destoroyah(z0);
    bignum_destoroyah(r2);
    //rf = r1+r3
    bignum* rf = bignum_add(*r1, *r3);

    bignum_destoroyah(r1);
    bignum_destoroyah(r3);

    bignum_destoroyah(z0);
    bignum_destoroyah(z1);
    bignum_destoroyah(z2);
    return rf;
}
Пример #23
0
/**
 * Perform an in place add into the source bignum. That is source += add
 */
void bignum_iadd(bignum* source, bignum* add) {
    bignum* temp = bignum_init();
    bignum_add(temp, source, add);
    bignum_copy(temp, source);
    bignum_deinit(temp);
}