
#ifdef __API_INTERN__
	#include "basevar.h"
	#include "ge_tools.h"
#else
	#include "c4d_tools.h"
	#include "c4d_general.h"
#endif

#include "c4d_basetime.h"



BaseTime::BaseTime(Real r)
{
	if (r>RCO 1.0e15) r=RCO 1.0e15; 
	if (r<RCO -1.0e15 ) r=RCO -1.0e15; 
	numerator = Floor(r* RCO 1000.0 + RCO 0.5); 
	denominator = RCO 1000.0; 
	Reduce();
}

BaseTime::BaseTime(Real z, Real n)
{ 
	Bool sgn = (z>=0.0) == (n>=0.0);

	numerator = Floor(Abs(z)+RCO 0.5); 
	denominator  = Floor(Abs(n)+RCO 0.5); 
	if (denominator<RCO 1.0)
	{
		GeBoom();
		denominator = 1.0;
	}

	if (!sgn) numerator = -numerator;
	Reduce();
}

void BaseTime::SetDenominator(Real r) 
{ 
	denominator=r; 
	if (denominator<RCO 1.0)
	{
		GeBoom();
		denominator = 1.0;
	}
}

void BaseTime::Quantize(Real fps)
{
	if (fps<RCO 1.0)
	{
		GeBoom();
		fps = 1.0;
	}
	numerator = Floor(Floor(numerator*fps)/Floor(denominator));
	denominator  = Floor(fps);
	Reduce();
}

void BaseTime::Reduce(void)
{ 
	Real z,n,m;

	z=Abs(numerator);
	n=Abs(denominator);

	if (z<0.001 || n<0.001)
	{
		numerator=0.0;
		denominator=1.0;
	}
	else if (z<MAXLONGf && n<MAXLONGf)
	{
		LONG iz=(LONG)z,in=(LONG)n,im;

		if (in==0) // failsafe
		{
			numerator=0.0; 
			denominator=1.0;
		}
		else
		{
			do
			{
				im=iz%in;
				iz=in;in=im;
			}while(im);

			numerator/=Real(iz);
			denominator/=Real(iz);
		}
	}
	else
	{
		LReal div = 1.0e18/FMax(LReal(z),LReal(n));
		if (div<1.0)
		{
			z*=div;
			n*=div;
			numerator*=div;
			denominator*=div;
		}
		if (n<1.0) { n=1.0; denominator=1.0; }
		
		do
		{
			m=FMod(z,n);
			z=n;n=m;
		}while(m>=0.5);

		numerator/=z;
		denominator/=z;
	}
}
