예제 #1
0
decimal decimal::operator *(const decimal& value) const
{
	const decimal& a = length() <= value.length() ? *this : value;
	const decimal& b = length() > value.length() ? *this : value;
	if (a.isZero()) {
		return decimal(0);
	} else if (a.isUnity()) {
		return b;
	}
	decimal c;
	const auto as = a.length();
	const auto bs = b.length();
	c.digits.resize(as + bs);
	for (size_t i = 0; i < as; i++) {
		const digit ad = a[i];
		if (ad == 0) {
			continue;
		}
		decimal tmp;
		tmp.digits.resize(bs + i + 1);
		digit carry = 0;
		for (size_t j = 0; j < bs; j++) {
			digit d = b[j] * ad + carry;
			carry = d / 10;
			tmp[j + i] = d - (carry * 10);
		}
		if (carry) {
			tmp[bs + i] = carry;
		} else {
			tmp.digits.resize(bs + i);
		}
		c += tmp;
	}
	c.remove_lz();
	return c;
}
예제 #2
0
char decimal::relation_to(const decimal& b) const
{
	const decimal& a = *this;
	const auto as = a.length();
	const auto bs = b.length();
	if (as > bs) {
		return +1;
	} else if (bs > as) {
		return -1;
	}
	for (auto i = as; i > 0; i--) {
		digit d = a[i - 1] - b[i - 1];
		if (d > 0) {
			return +1;
		} else if (d < 0) {
			return -1;
		}
	}
	return 0;
}
예제 #3
0
decimal decimal::operator -=(const decimal& b)
{
	if (b.isZero()) {
		return *this;
	}
	decimal& a = *this;
	const size_t w = a.length();
	if (b.length() > w) {
		throw underflow_error("Negative values not allowed");
	}
	bool borrow = false;
	for (size_t i = 0; i < w; i++) {
		digit d = a[i] - b[i] - (borrow ? 1 : 0);
		borrow = d < 0;
		a[i] = borrow ? 10 + d : d;
	}
	if (borrow) {
		throw underflow_error("Negative values not allowed");
	}
	remove_lz();
	return *this;
}
예제 #4
0
decimal decimal::operator +=(const decimal& b)
{
	if (isZero()) {
		*this = b;
		return *this;
	} else if (b.isZero()) {
		return *this;
	}
	decimal& a = *this;
	const size_t w = max(a.length(), b.length());
	digits.resize(w + 1);
	bool carry = false;
	for (size_t i = 0; i < w; i++) {
		digit d = a[i] + b[i] + (carry ? 1 : 0);
		carry = d >= 10;
		a[i] = carry ? d - 10 : d;
	}
	if (carry) {
		a[w] = 1;
	} else {
		digits.resize(w);
	}
	return *this;
}
예제 #5
0
decimal decimal::parallel_multiply(const decimal& l, const decimal& r)
{
	const decimal& a = l.length() <= r.length() ? l : r;
	const decimal& b = l.length() > r.length() ? l : r;
	if (a.isZero()) {
		return decimal(0);
	} else if (a.isUnity()) {
		return b;
	}
	const auto as = a.length();
	const auto bs = b.length();
	const size_t cores = std::thread::hardware_concurrency();
	const size_t workers = min<size_t>(cores, (as / 1000));
	if (workers == 0) {
		return l * r;
	}
	decimal result;
	result.digits.resize(as + bs);
	mutex mx;
	function<int(size_t, size_t)> partial_product = [&a, &b, as, bs, &mx, &result] (size_t begin, size_t end) {
		decimal c;
		c.digits.resize(as + bs);
		decimal tmp;
		tmp.digits.reserve(bs + end + 1);
		for (size_t i = begin; i < end; i++) {
			const digit ad = a[i];
			if (ad == 0) {
				continue;
			}
			fill(tmp.digits.begin(), tmp.digits.end(), 0);
			tmp.digits.resize(bs + i + 1);
			digit carry = 0;
			for (size_t j = 0; j < bs; j++) {
				digit d = b[j] * ad + carry;
				carry = d / 10;
				tmp[j + i] = d - (carry * 10);
			}
			if (carry) {
				tmp[bs + i] = carry;
			} else {
				tmp.digits.resize(bs + i);
			}
			c += tmp;
		}
		lock_guard<mutex> lock(mx);
		result += c;
		return 0;
	};
	vector<future<int>> futures;
	futures.reserve(workers);
	for (size_t worker = 0; worker < workers; worker++) {
		const auto begin = (as * worker) / workers;
		const auto end = (as * (worker + 1)) / workers;
		futures.emplace_back(async(std::launch::async, partial_product, begin, end));
	}
	for (size_t worker = 0; worker < workers; worker++) {
		auto& future = futures[worker];
		future.get();
	}
	result.remove_lz();
	return result;
}