Infinity Calculator implementation for Assignment 2 in Computer Organization.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

161 lines
3.9 KiB

void infint_add(infint_t *ii, uint8_t n) {
if(ii->sign) {
ii->sign = 0;
infint_sub(ii, n);
ii->sign ^= 1;
} else {
uint8_t acc = n;
acc += ii->data[0];
ii->data[0] = acc % 100;
acc /= 100;
for (size_t i = 1; acc > 0; ++i) {
infint_grow_to(ii, i + 1);
acc += ii->data[i];
ii->data[i] = acc % 100;
acc /= 100;
}
}
}
void infint_sub(infint_t *ii, uint8_t n) {
if(ii->sign) {
ii->sign = 0;
infint_add(ii, n);
ii->sign = 1;
} else if (infint_abs_less_than(ii, n)) {
ii->data[0] = n - ii->data[0];
ii->sign = 1;
} else {
size_t old_size = ii->size;
infint_t *tmp = infint_new(ii->size);
tmp->size = ii->size;
tmp->data[0] = n;
infint_comp(tmp);
infint_add2(ii,tmp);
infint_free(tmp);
if (ii->size > old_size) ii->data[ii->size - 1] = 0;
while (ii->data[ii->size - 1] == 0 && ii->size > 1) ii->size -= 1;
}
}
void infint_mult(infint_t *ii, uint8_t n) {
if (n == 0) {
memset(ii->data, 0, ii->size);
ii->size = 1;
ii->sign = 0;
} else {
uint16_t acc = 0;
for (size_t i = 0; i < ii->size; ++i) {
acc += n * ii->data[i];
ii->data[i] = acc % 100;
acc /= 100;
}
if (acc > 0) {
infint_grow_to(ii, ii->size + 1);
ii->data[ii->size - 1] = acc;
}
}
}
uint8_t infint_div(infint_t *ii, uint8_t n) {
uint16_t acc = 0;
for (size_t i = ii->size - 1; i != -1; --i) {
acc += ii->data[i];
ii->data[i] = acc / n;
acc = (acc % n) * 100;
}
while (ii->data[ii->size - 1] == 0 && ii->size > 1) ii->size -= 1;
return acc / 100;
}
void infint_add2(infint_t *ii1, infint_t *ii2) {
if(ii1->sign ^ ii2->sign) {
ii1->sign = ii2->sign;
infint_sub2(ii1, ii2);
ii1->sign ^= 1;
} else {
uint8_t acc = 0;
infint_grow_to(ii1, ii2->size);
for(size_t i = 0; i < ii2->size; ++i) {
acc += ii1->data[i];
acc += ii2->data[i];
ii1->data[i] = acc % 100;
acc /= 100;
}
for(size_t i = ii2->size; acc > 0; ++i) {
infint_grow_to(ii1, i + 1);
acc += ii1->data[i];
ii1->data[i] = acc % 100;
acc /= 100;
}
}
}
void infint_sub2(infint_t *ii1, infint_t *ii2) {
if(ii1->sign ^ ii2->sign) {
ii1->sign = ii2->sign;
infint_add2(ii1, ii2);
ii1->sign = !ii2->sign;
} else if(infint_abs_less_than2(ii1,ii2)) {
if (ii2->size < ii1->size) {
infint_grow_to(ii2,ii1->size);
ii2->size = ii1->size;
}
infint_comp(ii2);
infint_add2(ii1,ii2);
infint_comp(ii1);
infint_comp(ii2);
while (ii1->data[ii1->size - 1] == 0 && ii1->size > 1) ii1->size -= 1;
while (ii2->data[ii1->size - 1] == 0 && ii2->size > 1) ii2->size -= 1;
ii1->sign ^= 1;
} else {
size_t old_size = ii1->size;
if (ii2->size < ii1->size) {
infint_grow_to(ii2,ii1->size);
ii2->size = ii1->size;
}
infint_comp(ii2);
infint_add2(ii1,ii2);
infint_comp(ii2);
if (ii1->size > old_size) ii1->data[ii1->size - 1] = 0;
while (ii1->data[ii1->size - 1] == 0 && ii1->size > 1) ii1->size -= 1;
while (ii2->data[ii1->size - 1] == 0 && ii2->size > 1) ii2->size -= 1;
}
}
void infint_mult2(infint_t *ii1, infint_t *ii2) {
if (ii1->size == 1 && ii2->size == 1) {
uint16_t acc = ii1->data[0];
acc *= ii2->data[0];
infint_grow_to(ii1, 2);
ii1->data[0] = acc % 100;
ii1->data[1] = acc / 100;
} else if(ii1->size == 1) {
uint8_t tmp = ii1->data[0];
free(ii1->data);
ii1->data = calloc(ii2->size, sizeof(uint8_t));
memcpy(ii1->data, ii2->data, ii2->size);
ii1->capacity = ii1->size = ii2->size;
infint_mult(ii1, tmp);
} else if(ii2->size == 1) {
infint_mult(ii1, ii2->data[0]);
} else {
infint_t *acc1, *acc2;
acc2 = infint_new(ii1->size * ii2->size);
for(size_t i = 0; i < ii2->size; ++i) {
if(ii2->data[i] != 0) {
acc1 = infint_clone(ii1);
infint_mult(acc1, ii2->data[i]);
infint_shift_right(acc1, i);
infint_add2(acc2,acc1);
infint_free(acc1);
}
}
free(ii1->data);
ii1->data = acc2->data;
ii1->size = acc2->size;
ii1->capacity = acc2->capacity;
free(acc2);
}
ii1->sign ^= ii2->sign;
}