Example #1
0
void ShiftLeftTests::should_correctly_shift_by_large_number() {
	BigNumber sut = BigNumber("4294967295") << BigNumber("510");

	std::string sutStr = sut.toString();

	assert(sut.toString() == "14396524139186276442508073949701635698831569246696291770774319487926989897218320177502543451331982168338021057104758899847644938664143288301840606092160112084910080");
}
Example #2
0
/// Return a BigNumber object.
// Will create a BigNumber object out of a stored string, at given precision (in decimal) - that's why the aPrecision argument must be here - but only if no BigNumber object is already present
BigNumber* LispNumber::Number(LispInt aBasePrecision)
{
  if (!iNumber)
  {  // create and store a BigNumber out of string
    assert(iString.ptr());
    RefPtr<LispString> str;
    str = iString;
    // aBasePrecision is in digits, not in bits, ok
    iNumber = NEW BigNumber(str->c_str(), aBasePrecision, BASE10);
  }

  // check if the BigNumber object has enough precision, if not, extend it
  // (applies only to floats). Note that iNumber->GetPrecision() might be < 0
  else if (!iNumber->IsInt() && iNumber->GetPrecision() < (LispInt)digits_to_bits(aBasePrecision, BASE10))
  {
    if (iString)
    {// have string representation, can extend precision
      iNumber->SetTo(iString->c_str(),aBasePrecision, BASE10);
    }
    else
    {
  // do not have string representation, cannot extend precision!
    }
  }
  return iNumber;
}
Example #3
0
BigNumber& BigNumber::operator-=(const BigNumber& rhs)
{
	if(_sign && rhs._sign)
	{
		if(moduloComparisonMore(rhs))
		{
			subtractionMethod(rhs);
			_sign = true;
		}
		else
		{
			*this = BigNumber(rhs).subtractionMethod(*this);
			_sign = false;
		}
	}
	else if(_sign && !rhs._sign)
	{
		addMethod(rhs);
		_sign = true;
	}
	else if(!_sign && rhs._sign)
	{
		addMethod(rhs);
		_sign = false;
	}
	else if(!_sign && !rhs._sign)
	{
		if(moduloComparisonMore(rhs))
		{
			subtractionMethod(rhs);
			_sign = false;
		}
		else
		{
			*this = BigNumber(rhs).subtractionMethod(*this);
			_sign = true;
		}
	}

	_stringFormat = NULL;
	return *this;
}
Example #4
0
BigNumber BigNumber::operator%(const BigNumber &y) const
{
    BigNumber l;
    for (auto i = 0u; i < data_.size(); ++i)
    {
        l.data_.push_front(data_[data_.size() - i - 1]);
        auto div = findDiv(l, y);
        l = l - y * BigNumber(div);
    }
    return l;
}
int main(void) {
    HAL_Init();
    SystemClock_Config();

    PCD8544Init();

  while(1) {

    ClearDisplayBuffer(); //erase
    BigNumber(msTicks); //draw
    PCD8544Update();      //display
    HAL_Delay(1000);
  }
}
Example #6
0
BigNumber BigNumber::operator ~() const {
	//Corner case: number is zero.
	if(this->is_zero()) {
		return BigNumber("1");
	}

	BigNumber result;
	Block* current_block = NULL;
    int32_t offset = 0, max_offset = -1;
	element_type operation_result = 0;
	uint32_t zero_elements = 0;

	for(BigNumberIterator it = this->get_lowest_byte(); it != ++this->get_highest_byte(); ++it) {
		operation_result = ~(*it);
		
		if(operation_result == 0) {
			zero_elements++;
			continue;
		}

		for(int i = 1; i <= zero_elements; ++i) {
			if(offset > max_offset) {
				current_block = &result.push_back_new_block();
				offset = 0;
				max_offset = current_block->get_size() - 1;
			}

			current_block->get_bits_array()[offset++] = 0;
		}

		if(offset > max_offset) {
			current_block = &result.push_back_new_block();
			offset = 0;
			max_offset = current_block->get_size() - 1;
		}

		current_block->get_bits_array()[offset++] = operation_result;

		current_block->trailing_zeros = current_block->get_size() - offset;
	}

	return result;
}
Example #7
0
BigNumber BigNumber::operator <<(const BigNumber& x) const {
	//Corner cases: operand or swifted number is zero.
	if(this->is_zero()) {
		return BigNumber();
	}

	if(x.is_zero()) {
		return *this;
	}

	BigNumber result(*this), counter(x);
	BigNumberIterator highest_byte = result.get_highest_byte(), lowest_byte = result.get_lowest_byte();

	uint8_t shift_value = BitShiftsAlgorithms::expand_number_at_lowest_bytes_end(result, counter);

	BitShiftsAlgorithms::expand_number_at_highest_bytes_end(result, highest_byte, shift_value);

	BitShiftsAlgorithms::shift_left_number(result, highest_byte, lowest_byte, shift_value);

	return result;
}
Example #8
0
unsigned BigNumber::findDiv(const BigNumber &dividend, const BigNumber &divisor) const
{
    unsigned first = 0;
    unsigned last = BASE;
    
    unsigned it;
    int64_t count, step;
    count = last - first;
    while (count > 0)
    {
        it = first;
        step = count / 2;
        it += step;
        if (!(dividend < BigNumber(it) * divisor))
        {
            first = ++it;
            count -= step + 1;
        }
        else
            count = step;
    }
    return first - 1;
}
Example #9
0
	BigNumber()
	{
		*this=BigNumber(string("0"));
	}
Example #10
0
void BigNumber::subtract(const BigNumber& minuend, const BigNumber& subtrahend, BigNumber& result) {
	//Corner case: subtrahend is zero.
	if(subtrahend.is_zero()) {
		result = minuend;
		return;
	}
    
	//Equality check is required to subtract smaller number from larger.
	equality_check compare_result = minuend.compare_to(subtrahend);

	//Corner case: equal numbers.
	if(compare_result == EQUAL) {
		result = BigNumber();
		return;
	}

	//Set result sign.
	if(compare_result == SECOND_BIGGER) {
		result.is_negative = true;
	}

	//Remember relation between subtracted numbers.
	const BigNumber& greater_number = (result.is_negative == false) ? minuend : subtrahend;
	const BigNumber& smaller_number = (&greater_number == &minuend) ? subtrahend : minuend;

	//Set iterators to lowest bytes.
	BigNumberIterator greater_it = greater_number.get_lowest_byte();
	BigNumberIterator smaller_it = smaller_number.get_lowest_byte();

    //Latest subtraction value.
    ex_element_type operation_result = 0;

    //Offset in last block where result may be stored.
    int32_t offset = 0, max_offset = -1;

    //Current block pointer - to avoid calls to list every time.
    Block* block = NULL;

	//Borrow flag - indicates if current computation is using "borrowed" values.
    bool borrow = false;

	uint64_t zero_elements = 0;

    //Subtract smaller number from equal subset of higher number.
	for(;smaller_it != ++smaller_number.get_highest_byte(); ++smaller_it, ++greater_it, operation_result = 0) { // TODO: AG: Should not count ++smaller_number.get_highest_byte() every time
        
		//Copy current byte from greater number to result buffer.
		operation_result = *greater_it;

		if(borrow) {
			if(*greater_it > 0) {
				//Decrement value if this is the digit from which the borrow is taken (first non-zero digit before the loan taker).
				--operation_result;
				borrow = false;
			} else {
				//This digit is also beneficient of loan, enjoy it.
				operation_result += ELEMENT_MAX;
			}
		}
        
		//Enter "borrow mode" and take extra value.
		if(operation_result < *smaller_it) {
			borrow = true;
			operation_result += ELEMENT_MAX + 1;
		}

		//Actual subtraction takes place here.
		operation_result -= *smaller_it;

        //Zero-results are counted, but not immedietaly appended to number.
        //This is to avoid redundant blocks with arrays filled with zeros at the end of chain.
        if(operation_result == 0) {
            ++zero_elements;
            continue;
        }
            
        //If the result is non-zero, insert all preceeding zeros to number.
        for(;zero_elements > 0; --zero_elements, ++offset) {
            if(offset > max_offset) {
                block = &result.push_back_new_block();
                offset = 0;
                max_offset = block->get_size() - 1;
            }
                
            block->get_bits_array()[offset] = 0;
        }
            
        if(offset > max_offset) {
            block = &result.push_back_new_block();
            offset = 0;
            max_offset = block->get_size() - 1;
        }
            
        //Insert non-zero result into the chain.
        block->get_bits_array()[offset++] = (element_type)operation_result;
        block->trailing_zeros = block->get_size() - offset;
    }

    //Rewrite the rest of larger number into result.
    for(;greater_it != ++greater_number.get_highest_byte(); ++greater_it) { // TODO: AG: Should not count ++greater_number.get_highest_byte() every time
        //Copy current byte from greater number to result buffer.
		operation_result = *greater_it;

		if(borrow) {
			if(*greater_it > 0) {
				//Decrement value if this is the digit from which the borrow is taken (first non-zero digit before the loan taker).
				--operation_result;
				borrow = false;
			} else {
				//This digit is also beneficient of loan, enjoy it.
				operation_result += ELEMENT_MAX;
			}
		}

		//Zero-results are counted, but not immedietaly appended to number.
        //This is to avoid redundant blocks with arrays filled with zeros at the end of chain.
        if(operation_result == 0) {
            ++zero_elements;
            continue;
        }
            
        //If the result is non-zero, insert all preceeding zeros to number.
        for(;zero_elements > 0; --zero_elements, ++offset) {
            if(offset > max_offset) {
                block = &result.push_back_new_block();
                offset = 0;
                max_offset = block->get_size() - 1;
            }
                
            block->get_bits_array()[offset] = 0;
        }
            
        if(offset > max_offset) {
            block = &result.push_back_new_block();
            offset = 0;
            max_offset = block->get_size() - 1;
        }
            
        //Insert non-zero result into the chain.
        block->get_bits_array()[offset++] = (element_type)operation_result;
        block->trailing_zeros = block->get_size() - offset;
    }
}
Example #11
0
void BigNumber::add(const BigNumber& arg1, const BigNumber& arg2, BigNumber& result) {
	equality_check ec;
	ex_element_type current_sum = 0;
	element_type carry = 0;

	if (arg1.get_actual_size() > arg2.get_actual_size()) {
		result = BigNumber(arg1);
		ec = FIRST_BIGGER;
	}
	else {
		result = BigNumber(arg2);
		ec = SECOND_BIGGER;
	}

	BigNumberIterator larger_it = (ec == FIRST_BIGGER) ? arg1.get_lowest_byte() : arg2.get_lowest_byte();
	BigNumberIterator smaller_it = (ec == FIRST_BIGGER) ? arg2.get_lowest_byte() : arg1.get_lowest_byte();

	std::list<Block>::iterator it;
	for (it = result.blocks.begin(); it != result.blocks.end(); ++it) {
		it->trailing_zeros = it->elements;
	}

	BigNumberIterator result_it = result.get_lowest_byte();

	while (smaller_it != ++smaller_it.number.get_highest_byte()) {
		current_sum = (ex_element_type)*smaller_it + (ex_element_type)*larger_it + (ex_element_type)carry;
		*result_it = (element_type)current_sum;
		if ((element_type)current_sum != 0) {
			(*result_it.get_block_iterator()).trailing_zeros 
				=  (*result_it.get_block_iterator()).get_size() - 1 - result_it.get_offset();
		}
		carry = CARRY_SHIFT(current_sum);

		++smaller_it;
		++larger_it;
		++result_it;
	}

	while (larger_it != larger_it.number.end()) { // TODO: KK: Don't add trailing zeros (check if iterator reaches actual size)
		current_sum = *larger_it + carry;
		*result_it = (element_type)current_sum;
		if ((element_type)current_sum != 0) {
			(*result_it.get_block_iterator()).trailing_zeros 
				=  (*result_it.get_block_iterator()).get_size() - 1 - result_it.get_offset();
		}
		carry = CARRY_SHIFT(current_sum);

		++larger_it;
		++result_it;
	}

	if (carry != 0) { // TODO: KK: Corner case, should be tested
		--result_it;
		Block& block = result.push_back_new_block();
		++result_it;
		
		*result_it = (element_type)carry;
		
		--block.trailing_zeros;
	}
}
Example #12
0
void ShiftLeftTests::should_correctly_shift_when_last_byte_has_available_space() {
	BigNumber one_bit_before = BigNumber("2097151") << BigNumber("2");

	assert(one_bit_before.toString() == "8388604");
}
Example #13
0
BigNumber BigNumber::operator ^(const BigNumber& x) const {
    
    //Corner cases to avoid problems with zero-operands.
    if(this->is_zero() && x.is_zero()) {
        return BigNumber();
    } else if(this->is_zero()) {
        return BigNumber(x);
    } else if(x.is_zero()) {
        return BigNumber(*this);
    }
    
    BigNumber result = BigNumber();
    
    //Determine which operand is smaller. If operands are of the same size, it doesn't matter.
    const BigNumber& smaller_number = x.get_actual_size() <= this->get_actual_size() ? x : *this;
    const BigNumber& greater_number = &smaller_number == this ? x : *this;
    
    //Iterators to currently XORed elements.
    BigNumberIterator smaller_it = smaller_number.get_lowest_byte();
    BigNumberIterator greater_it = greater_number.get_lowest_byte();
        
    //Counter of subsequent elements with zero value.
    uint64_t zero_elements = 0;

    //Latest XOR result.
    element_type operation_result = 0;

    //Offset in last block where result may be stored.
    int32_t offset = 0, max_offset = -1;

    //Current block pointer - to avoid calls to list every time.
    Block* block = NULL;
    
    //XORs smaller number with equal it's matching subset from greater number.
    for(;smaller_it != ++smaller_number.get_highest_byte(); ++smaller_it, ++greater_it) {
        operation_result = *smaller_it ^ *greater_it;
        
        if(operation_result == 0) {
            ++zero_elements;
            continue;
        }
        
        for(;zero_elements > 0; --zero_elements, ++offset) {
            if(offset > max_offset) {
                block = &result.push_back_new_block();
                offset = 0;
                max_offset = block->get_size() - 1;
            }

            block->get_bits_array()[offset] = 0;
        }
        
        if(offset > max_offset) {
            block = &result.push_back_new_block();
            offset = 0;
            max_offset = block->get_size() - 1;
        }
        
        block->get_bits_array()[offset++] = operation_result;
        block->trailing_zeros = block->get_size() - offset;
    }
    
    //XORs remaining part of greater number with zeros ("zero-padding from left" smaller number).
    for(;greater_it != ++greater_number.get_highest_byte(); ++greater_it) {
        operation_result = 0 ^ *greater_it;
        
        if(operation_result == 0) {
            ++zero_elements;
            continue;
        }
        
        for(;zero_elements > 0; --zero_elements, ++offset) {
            if(offset > max_offset) {
                block = &result.push_back_new_block();
                offset = 0;
                max_offset = block->get_size() - 1;
            }

            block->get_bits_array()[offset] = 0;
        }
        
        if(offset > max_offset) {
            block = &result.push_back_new_block();
            offset = 0;
            max_offset = block->get_size() - 1;
        }
        
        block->get_bits_array()[offset++] = operation_result;
        block->trailing_zeros = block->get_size() - offset;
    }

    return result;
}
// constructor
BigNumber::BigNumber() {
  BigNumber(0);
}
Example #15
0
 BigNumber number(Word* p) const {
     return BigNumber(p + stateWords);
 }
Example #16
0
void ShiftLeftTests::should_shift_by_nonmultiple_of_byte() {
	BigNumber shift_by_multiple_of_8_bytes = BigNumber("43981") << BigNumber("14");
	assert(shift_by_multiple_of_8_bytes.toString() == "720584704");
}
Example #17
0
void ShiftLeftTests::should_shift_by_multiple_of_byte() {
	BigNumber shift_by_multiple_of_8_bytes = BigNumber("43981") << BigNumber("16");
	assert(shift_by_multiple_of_8_bytes.toString() == "2882338816");
}
Example #18
0
void ShiftLeftTests::should_correctly_shift_when_there_is_exactly_required_amount_of_space() {
	BigNumber number_full = BigNumber("2097151") << BigNumber("3");

	assert(number_full.toString() == "16777208");
}
Example #19
0
BigNumber BigNumber::operator |(const BigNumber& x) const {
	//Corner cases: one or more operands are zero.
	if(this->is_zero() && x.is_zero()){
		return BigNumber();
	} else if(x.is_zero()) {
		return *this;
	} else if(this->is_zero()) {
		return x;
	}
    
    BigNumber result = BigNumber();
    
    //Determine which operand is smaller. If operands are of the same size, it doesn't matter.
    const BigNumber& smaller_number = x.get_actual_size() <= this->get_actual_size() ? x : *this;
    const BigNumber& greater_number = &smaller_number == this ? x : *this;
    
    //Iterators to currently ORed elements.
    BigNumberIterator smaller_it = smaller_number.get_lowest_byte();
    BigNumberIterator greater_it = greater_number.get_lowest_byte();

    //Latest XOR result.
    element_type operation_result = 0;

    //Offset in last block where result may be stored.
    int32_t offset = 0, max_offset = -1;

    //Current block pointer - to avoid calls to list every time.
    Block* block = NULL;
    
    //OR smaller number with equal it's matching subset from greater number.
    for(;smaller_it != ++smaller_number.get_highest_byte(); ++smaller_it, ++greater_it) {
        operation_result = *smaller_it | *greater_it;
        
        if(offset > max_offset) {
            block = &result.push_back_new_block();
            offset = 0;
            max_offset = block->get_size() - 1;
        }
        
        block->get_bits_array()[offset++] = operation_result;

		if(operation_result != 0) {
			block->trailing_zeros--;
		}
    }
    
    //OR remaining part of greater number with zeros ("zero-padding from left" smaller number).
    for(;greater_it != ++greater_number.get_highest_byte(); ++greater_it) {
        operation_result = 0 | *greater_it;
        
        if(offset > max_offset) {
            block = &result.push_back_new_block();
            offset = 0;
            max_offset = block->get_size() - 1;
        }
        
        block->get_bits_array()[offset++] = operation_result;
		
		if(operation_result != 0) {
			block->trailing_zeros--;
		}
    }

    return result;
}
Example #20
0
BigNumber BigNumber::operator &(const BigNumber& x) const {
    //Corner case: both operands are zeros. Return zero.
    if(this->is_zero() || x.is_zero()) {
        return BigNumber();
    }
    
    BigNumber result = BigNumber();
    
    //Number of iterations, minimal size of operands.
    uint64_t iterations = std::min(this->get_actual_size(), x.get_actual_size());
    
    {
        //Iterators to currently ANDed elements (bytes, values).
        BigNumberIterator this_iterator = this->get_lowest_byte();
        BigNumberIterator x_iterator = x.get_lowest_byte();
        
        //Counter of subsequent elements with zero value.
        uint64_t zero_elements = 0;
        
        //Latest AND result.
        element_type operation_result = 0;
        
        //Offset in last block where result may be stored.
        int32_t offset = 0, max_offset = -1;
        
        //Current block pointer - to avoid calls to list every time.
        Block* block = NULL;
                
        for(uint64_t i = 1; i <= iterations; ++i, ++this_iterator, ++x_iterator) {
            //Perform AND operation.
            operation_result = *this_iterator & *x_iterator;
            
            //Zero-results are counted, but not immedietaly appended to number.
            //This is to avoid redundant blocks with arrays filled with zeros at the end of chain.
            if(operation_result == 0) {
                ++zero_elements;
                continue;
            }
            
            //If the result is non-zero, insert all preceeding zeros to number.
            for(;zero_elements > 0; --zero_elements, ++offset) {
                if(offset > max_offset) {
                    block = &result.push_back_new_block();
                    offset = 0;
                    max_offset = block->get_size() - 1;
                }
                
                block->get_bits_array()[offset] = 0;
            }
            
            if(offset > max_offset) {
                block = &result.push_back_new_block();
                offset = 0;
                max_offset = block->get_size() - 1;
            }
            
            //Insert non-zero result into the chain.
            block->get_bits_array()[offset++] = operation_result;
            block->trailing_zeros = block->get_size() - offset;
        }
    }
    
    return result;
}
Example #21
0
void ShiftLeftTests::should_correctly_shift_when_extra_element_must_be_allocated() {
	BigNumber one_bit_overflow = BigNumber("2097151") << BigNumber("4");

	assert(one_bit_overflow.toString() == "33554416");
}