/*
								+--------------------------------+
								|                                |
								|   ***  Exact arithmetic  ***   |
								|                                |
								|  Copyright © -tHE SWINe- 2014  |
								|                                |
								|           Exact2.inl           |
								|                                |
								+--------------------------------+
*/

#pragma once
#ifndef __EXACT_MULTIPRECISION_FLOATING_POINT_ARITHMETIC_INTERNAL2_INCLUDED
#define __EXACT_MULTIPRECISION_FLOATING_POINT_ARITHMETIC_INTERNAL2_INCLUDED

/**
 *	@file Exact2.inl
 *	@author -tHE SWINe-
 *	@date 2014
 *	@brief second part of the internals for exact multi-precision floating-point arithmetic
 */

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(TType f_value,
	expansion_internal::TFromScalar_Tag UNUSED(t_tag))
{
	/*typedef*/ typename CCheckSize<1>::CAssert /*CSizeCheck*/();
	m_p_value[0] = f_value;
	Uninitialized_Contract(1);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(TType f_value,
	expansion_internal::TFromScalar_ZeroPad_Tag UNUSED(t_tag))
{
	enum {
		n_min_size = (_n_max_coeff_num > 1)? _n_max_coeff_num : 1 // bigger size is not a problem, the caller knows it will be zero-padded, do not produce a warning
	};
	/*typedef*/ typename CCheckSize<n_min_size>::CAssert /*CSizeCheck*/();
	m_p_value[0] = f_value;
	Uninitialized_Contract(1);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(unsigned int n_size,
	const TType *p_value, expansion_internal::TFromArray_Tag UNUSED(t_tag))
{
	_ASSERTE(p_value < m_p_value || p_value >= m_p_value + _n_max_coeff_num); // make sure that the p_value does not point to this array
	_ASSERTE(n_size == _n_max_coeff_num); // must match, otherwise we have no way to print a compile-time warning that the expansion is unnecessarilyl large
	for(unsigned int i = 0; i < n_size; ++ i)
		m_p_value[i] = p_value[i];
	m_n_size = _n_max_coeff_num; // just set the size, there will never be zero-padding

	// note that the array passed may not be ascending or may be overlapping: this will be
	// checked in the destructor, for performance reasons (there is only a few ways to modify
	// the expansion inplace, the chances that a malformed expansion are not too large (unless
	// the first operation is multiply by zero or compress))
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(unsigned int n_size,
	const TType *p_value, expansion_internal::TFromArray_ZeroPad_Tag UNUSED(t_tag))
{
	_ASSERTE(p_value < m_p_value || p_value >= m_p_value + _n_max_coeff_num); // make sure that the p_value does not point to this array
	_ASSERTE(n_size <= _n_max_coeff_num); // can't be greater
	for(unsigned int i = 0; i < n_size; ++ i)
		m_p_value[i] = p_value[i];
	Uninitialized_Contract(n_size); // the size may be zero

	// note that the array passed may not be ascending or may be overlapping: this will be
	// checked in the destructor, for performance reasons (there is only a few ways to modify
	// the expansion inplace, the chances that a malformed expansion are not too large (unless
	// the first operation is multiply by zero or compress))
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(TType f_left,
	TType f_right, expansion_internal::TFromTwoSum_Tag UNUSED(t_tag))
{
	/*typedef*/ typename CCheckSize<2>::CAssert /*CSizeCheck*/(); // without CAssert it will not check
	CBase::Two_Sum(m_p_value[0], m_p_value[1], f_left, f_right);
	Uninitialized_Contract(2);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(TType f_left,
	TType f_right, expansion_internal::TFromTwoDiff_Tag UNUSED(t_tag))
{
	/*typedef*/ typename CCheckSize<2>::CAssert /*CSizeCheck*/(); // without CAssert it will not check
	CBase::Two_Diff(m_p_value[0], m_p_value[1], f_left, f_right);
	Uninitialized_Contract(2);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(TType f_left,
	TType f_right, expansion_internal::TFromTwoProd_Tag UNUSED(t_tag))
{
	/*typedef*/ typename CCheckSize<2>::CAssert /*CSizeCheck*/(); // without CAssert it will not check
	CBase::Two_Product(m_p_value[0], m_p_value[1], f_left, f_right);
	Uninitialized_Contract(2);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(TType f_scalar,
	expansion_internal::TFromScalarSquare_Tag UNUSED(t_tag))
{
	/*typedef*/ typename CCheckSize<2>::CAssert /*CSizeCheck*/(); // without CAssert it will not check
	CBase::Square(m_p_value[0], m_p_value[1], f_scalar);
	Uninitialized_Contract(2);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::~CExpansion()
{
	CBase::ExpansionCheck(m_n_size, m_p_value);
	// run the check

	// note that the coefficients of expansions are not initialized by default,
	// if the initialization is somehow skipped, this is more than likely to complain.
}

#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200

// this is only needed in msvc 6.0 for access by traits
template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline T &CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::f_At(unsigned int n_index)
{
	_ASSERTE(m_n_size <= n_max_coeff_num);
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200
	_ASSERTE((!n_index && n_max_coeff_num > 0) || n_index < m_n_size);
	// in msvc 6.0, the traits access expansion storage using operator [], at the time
	// when the expansion is not initialized yet, so we can't compare to it. but accessing
	// element 0 is generally safe, as expansions of 0 elements are not permitted
#else
	_ASSERTE(n_index < m_n_size);
#endif
	return m_p_value[n_index];
}

#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline T CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::operator [](unsigned int n_index) const
{
	_ASSERTE(m_n_size <= n_max_coeff_num);
	_ASSERTE(n_index < m_n_size);
	return m_p_value[n_index];
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline unsigned int CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::n_Size() const
{
	return m_n_size;
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Dump() const
{
	CBase::DumpExpansion(m_n_size, m_p_value);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Dump_Long() const // throw(std::bad_alloc)
{
	CBase::DumpExpansion_Long(m_n_size, m_p_value);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline unsigned int CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::n_Mantissa_Bit_Num() const
{
	return CBase::n_Mantissa_Width(m_n_size, m_p_value);
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline unsigned int CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::n_Mantissa_RepresentedBit_Num() const
{
	unsigned int n_result = 0;
	for(unsigned int i = 0, n = m_n_size; i < n; ++ i) {
		if(m_p_value[i]) {
			unsigned int w = n_Bit_Bandwidth(CFloatUtils<TType>::n_Get_Mantissa(m_p_value[i]));
			_ASSERTE(n_result <= UINT_MAX - w);
			n_result += w;
		}
	}
	return n_result;
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline MSVC6_OMMIT(typename) expansion_internal::CDynamicCastResult<
	MSVC6_OMMIT(typename) CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CSelf,
	MSVC6_OMMIT(typename) CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CDynamicSelf>::CResult
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::t_AsDynamic() const // note that calling this on dynamic expression causes an unnecessary copy
{
	return *this; // can save a few inline calls, the conversion takes care of everything
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Compact()
{
	if(n_max_coeff_num > n_max_fully_significant_coeff_num) { // compile-time constant
		if(m_n_size > n_max_fully_significant_coeff_num)
			Compress();
		// that's that, otherwise there is nothing to do
	}
	// otherwise an empty function
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline typename CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CCompactSelf
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::t_Compact() const
{
	enum {
		b_needs_treatment = n_max_coeff_num > n_max_fully_significant_coeff_num // if not set, this function can return *this
	};

#if 0
	if(b_needs_treatment) { // compile-time constant : the branch and the other part of the code should optimize away
		if(m_n_size <= n_max_fully_significant_coeff_num) {
			return CCompactSelf(m_n_size, m_p_value, expansion::from_array_zero_pad);
			// it is already smaller, just copy and return
		} else {
			CCompactSelf result(expansion_internal::uninitialized_construct);
			result.Uninitialized_Contract(CExactBase<T>::n_Compress(CCompactSelf::n_max_coeff_num,
				expansion_internal::CExpansionTraits<CCompactSelf>::p_Data(result), m_n_size, m_p_value)); // msvc 6.0 needs to use Uninitialized_Contract() and expansion traits here
			return result;
			// it is bigger, we need to compress
		}
	} else {
		//return *this; // can't do this, if b_needs_treatment is set: the size will be too big and static assertion will trigger

		typedef typename expansion_internal::CChooseType<CCompactSelf,
			const CSelf&, b_needs_treatment>::CResult CReturnType;
		// if this branch is active, we return const CSelf&, as the conversion is possible and no static asserts will trigger
		// if it is not active, we return CCompactSelf (with value of zero, but that never happens)

		return expansion_internal::CReturnConnector<CReturnType, !b_needs_treatment>()(*this); // return this only if !b_needs_treatment, otherwise returns zero value (but then this branch is never called)

		// t_odo - dont be a pig and implement this using an algorithm template
		// t_odo - remove the writable operator [](), it is easily abused. can't
	}
#else // 0
	typedef typename expansion_internal::CChooseType<CCompactSelf,
		const CSelf&, b_needs_treatment>::CResult CReturnType;
	// if the expansion is always shorter, just return const CSelf&
	// if it can be longer, return CCompactSelf after conversion by the CCompactionAlgorithm

	return expansion_internal::CCompactionAlgorithm<b_needs_treatment, CReturnType>()(*this);
#endif // 0
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Compress()
{
	Uninitialized_Contract(CExactBase<T>::n_Compress(_n_max_coeff_num, m_p_value, m_n_size, m_p_value));
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline typename CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CDynamicCompactSelf
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::t_Compressed() const // probably the only function which does not increase size of the expansion
{
	CDynamicCompactSelf result(expansion_internal::uninitialized_construct);
	result.Uninitialized_Contract(CExactBase<T>::n_Compress(CDynamicCompactSelf::n_max_coeff_num,
		expansion_internal::CExpansionTraits<CDynamicCompactSelf>::p_Data(result), m_n_size, m_p_value)); // msvc 6.0 needs to use Uninitialized_Contract() and expansion traits here
	return result;
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline T CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::f_Approximate() const
{
	return CExactBase<T>::f_ApproximateValue(m_n_size, m_p_value);
}

// t_odo - add fabs()
// t_odo - add comparison operators (most likely needs to be implemented using subtraction, as there are many arbitrary ways to represent the same value using expansions)

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Trim(unsigned int n_size) // clear entries n_size till the last one to zero; if dynamic size is allowed, it is simply changed to n_size
{
	_ASSERTE(n_size > 0); // don't create zero-length expansions
	_ASSERTE(n_size <= n_max_coeff_num && n_size <= m_n_size);

	if(m_n_size > n_size) {
		/*if(b_allow_dynamic) { // cannot be used, we allow conversion of static to dynamic expansions without explicit compression, and we will not do that. Trim() should be needed much less frequently than such compression, and therefore can be made more demanding
			_ASSERTE(m_n_size > 0);
			_ASSERTE(!*this || m_p_value[m_n_size - 1] != T(0)); // not true, if the dynamic expansion is converted from non-dynamic
			// dynamic expansions generally don't face this problem, as the expansion is only as long
			// as it needs to be, and the last element is always the most significant one

			unsigned int n_shift = m_n_size - n_size;
			for(unsigned int i = 0; i < n_size; ++ i) // for each element of the result
				m_p_value[i] = m_p_value[i + n_shift];
			// this can't be used, as it has a problem with spurious zeroes: if the most
			// significant value is not the last value, then the precision is reduced,
			// possibly even yielding zero result
		} else*/ {
			_ASSERTE(m_n_size > 0);
			unsigned int i = m_n_size;
			do {
				if(m_p_value[-- i] != T(0)) // there is always at least a single value
					break;
			} while(i > 0);
			// find the leading element of this expansion (typicaly equals m_n_size - 1 in the dynamic ones)

			if(i >= n_size) { // branch typically not taken if the expansion is dynamic and already short enough. only taken for longer static or dynamic with more precision in them
				unsigned int n_shift = i + 1 - n_size;
				// the amount of shift required (= the nubmer of elements to drop)

				for(unsigned int j = 0; j < n_size; ++ j) // for each element of the result
					m_p_value[j] = m_p_value[j + n_shift];
			}
			// see if a shift (always towards the least significant value) is still needed

			/*unsigned int n_src = m_n_size; // where we are reading from
			unsigned int n_dest = n_size; // where we are writing to
			while(n_src > 0) {
				-- n_src; // here
				if(m_p_value[i] != T(0)) {
					-- n_dest;
					if(n_dest > n_src)
						m_p_value[n_dest] = m_p_value[i];
					else if(n_dest == n_src)
						; // do nothing would read / write the same location
					else {
						// problem: we are readily overwriting existing values
					}
					if(!n_dest)
						break;
				}
			}
			while(n_dest > 0)
				m_p_value[-- n_dest] = 0;*/
			// another way of doing it: eliminate all the spurious zeroes, keep as much precision as possible
			// would need a temp array, and I guess it is not a priority here - a tighter representation can be reached using compression
		}
	}
	// in case a shift is needed

	// shift the values to the beginning, so that the current most significant value
	// (the one with the highest index) becomes the last value in the trimmed expansion

	Uninitialized_Contract(n_size);
	// contract the expansion to the given size
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
typename CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CSelf
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::operator -() const
{
	CSelf other(expansion_internal::uninitialized_construct);
	for(unsigned int i = 0, n = other.m_n_size = m_n_size; i < n; ++ i)
		other.m_p_value[i] = -m_p_value[i];
	return other;
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline typename CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CSelf
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::t_Abs() const
{
	return (f_Approximate() < 0)? -*this : *this; // not sure if there is a faster way of telling the sign. maybe not.
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
typename CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CSelf
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::t_Multiply_by_POT(int n_power_of_two_factor) const
{
	_ASSERTE(b_Is_POT(abs(n_power_of_two_factor)));
	CSelf other(expansion_internal::uninitialized_construct);
	for(unsigned int i = 0, n = other.m_n_size = m_n_size; i < n; ++ i)
		other.m_p_value[i] = m_p_value[i] * n_power_of_two_factor; // only a shift, unless infinity is reached (not handled here)
	return other;
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Multiply_by_POT(int n_power_of_two_factor) // can work in-place
{
	_ASSERTE(b_Is_POT(abs(n_power_of_two_factor)));
	for(unsigned int i = 0, n = m_n_size; i < n; ++ i)
		m_p_value[i] *= n_power_of_two_factor; // only a shift, unless infinity is reached (not handled here)
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
typename CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CSelf
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::t_Divide_by_POT(int n_power_of_two_factor) const
{
	_ASSERTE(n_power_of_two_factor); // division by zero
	_ASSERTE(b_Is_POT(abs(n_power_of_two_factor)));
	CSelf other(expansion_internal::uninitialized_construct);
	for(unsigned int i = 0, n = other.m_n_size = m_n_size; i < n; ++ i)
		other.m_p_value[i] = m_p_value[i] / n_power_of_two_factor; // only a shift, unless minimum exponent value is reached (not handled here)
	return other;
}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Divide_by_POT(int n_power_of_two_factor) // can work in-place
{
	_ASSERTE(n_power_of_two_factor); // division by zero
	_ASSERTE(b_Is_POT(abs(n_power_of_two_factor)));
	for(unsigned int i = 0, n = m_n_size; i < n; ++ i)
		m_p_value[i] /= n_power_of_two_factor; // only a shift, unless minimum exponent value is reached (not handled here)
}

/*typename expansion_internal::CMultiplicationResult<CSelf, CSelf>::CResult*/ // msvc 6.0 won't parse this
/*typename expansion_internal::CSquareResult<CSelf>::CResult*/ // msvc 6.0 won't parse this either
/*CExpansion<T, (_n_max_coeff_num == 2)? 6 : _n_max_coeff_num * _n_max_coeff_num * 2, _b_allow_dynamic>*/ // visual studio won't parse this, need to avoid ternary operator i guess
template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
CExpansion<T, expansion_internal::CSquareCoeffNum<_n_max_coeff_num>::n_result, _b_allow_dynamic>
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::t_Square() const // calculates square of the expansion, this is slightly faster than doing "a * a" as there are some redundant operations
{
	typedef typename expansion_internal::CSquareResult<CSelf> CAlgorithm;
	typedef typename CAlgorithm::CResult CResult;

	CResult result(expansion_internal::uninitialized_construct);
	result.Uninitialized_Contract(CAlgorithm::CImplementation::n_Run(
		expansion_internal::CExpansionTraits<CResult>::p_Data(result), m_n_size, m_p_value));

	/*enum {
		n_max_result_coeff_num = _n_max_coeff_num * _n_max_coeff_num * 2
	};

	typedef typename expansion_internal::CMultiplicationResult<CSelf, CSelf> CAlgorithm;
	typedef CExpansion<T, _n_max_coeff_num * _n_max_coeff_num * 2, _b_allow_dynamic> CResult;
	//typedef typename CAlgorithm::CResult CResult; // msvc 6.0 won't parse this

	CResult result(expansion_internal::uninitialized_construct);
	// keep this lower on the stack than the temp arrays so when the function
	// returns, it does not have to shuffle anything

	T p_hi[_n_max_coeff_num], p_lo[_n_max_coeff_num], p_sc[2 * _n_max_coeff_num];
	// need some temp arrays for calculating the product (the hand-optimized
	// fixed-size code would analogically require some temp variables)

	if(_b_allow_dynamic) { // compile-time constant
		_ASSERTE(m_n_size <= _n_max_coeff_num);
		result.Uninitialized_Contract(CExactBase<T>::n_Expansion_Square_EliminateZeroes(n_max_result_coeff_num,
			expansion_internal::CExpansionTraits<CResult>::p_Data(result),
			m_n_size, m_p_value, p_lo, p_hi, 2 * _n_max_coeff_num, p_sc));
		// dynamic size, need loops
	} else {
		_ASSERTE(m_n_size == _n_max_coeff_num);
		result.Uninitialized_Contract(CExactBase<T>::n_Expansion_Square(n_max_result_coeff_num,
			expansion_internal::CExpansionTraits<CResult>::p_Data(result),
			m_n_size, m_p_value, p_lo, p_hi, 2 * _n_max_coeff_num, p_sc));
		// can unroll loops here
	}*/
	// t_odo - run this through a square calculation algorithm, specialize for square of a single-element expansion, possibly 2x1 or 2x2 (but the inlining and optimizer should take care of those)

	return result;
}

/*template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::operator CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::bool_type() const
{
	return (f_Approximate() != T(0))? &CSelf::dummy_bool_type_value : (bool_type)0;
}*/
// msvc 6.0 can't have this here

/*template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::operator bool() const
{
	return f_Approximate() != T(0);
}*/
// beware, this causes problems if incorrectly mixing floats and exacts: the exact casts
// itself to bool and then serves as value of 1.0. use operator !() instead. note that this
// could be solved by the safe bool idiom, but here it is more confusing as the relational
// operators and operator []() are declared

/*template <class CRightExpansion>
template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline typename expansion_internal::CMultiplicationResult<typename CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CSelf, CRightExpansion>::CResult
	CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::operator *(const CRightExpansion &r_right) const
{
	typedef typename expansion_internal::CMultiplicationResult<CSelf, CRightExpansion> CAlgorithm;
	typedef typename CAlgorithm::CResult CResult;
	CResult result(expansion_internal::uninitialized_construct);

	unsigned int n_result_size = CAlgorithm::CImplementation::n_Run(
		expansion_internal::CExpansionTraits<CResult>::p_Data(result), m_n_size, m_p_value,
		expansion_internal::CExpansionTraits<CRightExpansion>::n_Size(r_right),
		expansion_internal::CExpansionTraits<CRightExpansion>::p_Data(r_right));
	result.Uninitialized_Contract(n_result_size);
	// multiply two expansions

	return result;
}*/
// does not parse in visual studio

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
inline CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::CExpansion(expansion_internal::TUninitializedConstruct_Tag UNUSED(t_tag))
{}

template <class T, const unsigned int _n_max_coeff_num, const bool _b_allow_dynamic>
void CExpansion<T, _n_max_coeff_num, _b_allow_dynamic>::Uninitialized_Contract(unsigned int n_size)
{
	_ASSERTE(n_size > 0); // don't create zero-length expansions
	_ASSERTE(n_size <= n_max_coeff_num);
	if(b_allow_dynamic) // compile-time constant
		m_n_size = n_size;
	else {
		for(; n_size < n_max_coeff_num; ++ n_size)
			m_p_value[n_size] = 0;
	}
}

#endif // !__EXACT_MULTIPRECISION_FLOATING_POINT_ARITHMETIC_INTERNAL2_INCLUDED
