• Create Account

# Rattrap

Member Since 03 Nov 2004
Offline Last Active Today, 06:14 AM

### Decimal to Binary Conversion

30 March 2012 - 12:48 PM

I'm posting this in the General Programming Forums, but it may really belong in the Math Forum...

While working on a project involving reading GIS data from a file, I somehow got myself side-tracked onto writing some functions that convert between the native floating points values to their binary IEEE754 equivalent (without taking the floating point variables pointer and casting it to a matching size integer pointer).

So I started researching the conversion process, and found this website with a procedure.

My code starts by separating the integral and fractional parts using the C/C++ modf function.

```/*
*	 FloatType is a template param = Input Type
*	 UnsignedIntegerType is a template param = Output Type
*	 MantissaBitCount is a template param stating the number of bits to use to store the mantissa in the output
*	 ExponentBitCount is a template param stating the number of bits to use to store the exponent in the output
*	 FindMostSignificantBit is a function that returns the highest flagged significant bit in an integer.
*
*
*	 MantissaPivot will eventually be translated to the exponent
*
*	 Unlike the example I am multiplying by 256 (instead of 2), allowing for 8 bits to be extracted after each iteration.
*/

const FloatType Zero(0);

const FloatType One(1);
const FloatType Factor(256);
const UnsignedIntegerType FactorSize(8);
int MantissaSize(-1);
int MantissaPivot(-1);

/* Used to test for infinity */
const bool GreaterThanZero(Input > Zero);
/* Used to test for overflow */
const bool GreaterThanOne(Input > One);

UnsignedIntegerType Mantissa(0);
do
{
Mantissa <<= FactorSize;

FloatType Integral;
const FloatType Fractional(std::modf(Input, &Integral));
/*    This fails with large Integrals    */
const UnsignedIntegerType ToMantissa(static_cast<UnsignedIntegerType>(Integral));

if(MantissaSize == -1)
{
if((ToMantissa == 0) && (GreaterThanOne == true))
{
/*	 Number was too large to cast to an int	 */
}

/*	 Initial Length	 */
const int MostSignificantBit(FindMostSignificantBit(ToMantissa));
MantissaSize = MostSignificantBit;
/*	 Number of bits before most significant bit	 */
MantissaPivot = (MostSignificantBit > 0) ? (MostSignificantBit - 1) : 0;
}
else
{
/*	 I don't know what to call this other than non-initial	 */
if((Mantissa == 0) && (ToMantissa != 0))
{
const int MostSignificantBit(FindMostSignificantBit(ToMantissa));
/*
*	 Number of bits before most significant bit
*	 At this point, we are dealing with the decmal and a negative
*	 number.  The means we start counting from the highest possible
*	 bit count the number of bits between it and the most siginifcant
*	 bit, including the most signficant bit itself.
*/
MantissaPivot -= (static_cast<int>(FactorSize) - MostSignificantBit + 1);
/*
*	 Don't count the leading 0's, since there was no significant values
*	 stored in the mantissa yet.
*/
MantissaSize += MostSignificantBit;
}
else
{
if(Mantissa == 0)
{
MantissaPivot -= FactorSize;
}
else
{
MantissaSize += FactorSize;
}
}
}
Mantissa |= ToMantissa;

Input = Fractional * Factor;
}
while((MantissaSize < MantissaBitCount) && (Input > Zero));
// More code follows for constructing the binary after it has been parsed into the mantissa and exponent

```

As on the example website, I try taking the Integral part and convert it to a native integer. The problem I'm having is if Integral part of the float is larger than what can be stored in a the output integer. Casting to a larger type is not really an option, since the code supports doubles and 64-bit integers. Any ideas on how to convert these large values into a usable mantissa and exponent without using an non-standard cheats?

### Issue with D3D9 and WS_EX_COMPOSITED

27 January 2011 - 08:11 AM

I've been building my own C++ win32 wrapper. I wanted to start adding a Direct3D9 control to my library, so I started going through the D3D9 tutorials in the SDK. I did things slightly different from the example, creating a parent form first, then creating a child window within it that. The child window is what IDirect3DDevice9 is associated with. I included the following code in the message loop after the windows had been created.

```		// Error checking code removed for brevity.  All are successful.

Direct3DDevice9->Clear( 0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,0,0), 1.0f, 0 );
Direct3DDevice9->BeginScene();
Direct3DDevice9->EndScene();
Direct3DDevice9->Present(0, 0, 0, 0);
```

IDirect3DDevice9 creation code
```
IDirect3DDevice9* Direct3DDevice9Raw(nullptr);
D3DPRESENT_PARAMETERS PresentationParameters;
ZeroMemory(&PresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
PresentationParameters.Windowed = TRUE;
PresentationParameters.BackBufferFormat = D3DFMT_UNKNOWN;
Result = Direct3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, WindowHandle, D3DCREATE_HARDWARE_VERTEXPROCESSING, &PresentationParameters, &Direct3DDevice9Raw);
if(Result != D3D_OK)
{
return -1;
}
```

The desired effect would be the child window would appear red, but I wasn't seeing anything. Everything had been initialized successfully. After some fiddling around, I discovered the culprit. My parent form uses the WS_EX_COMPOSITED extended window style. When i removed this, my red box shows up. Does anyone know if there is a way to get this to work, while keeping WS_EX_COMPOSITED on the parent form?

### End of the world may be near - Duke Nukem Forever at PAX

03 September 2010 - 08:59 AM

This may be one of the signs of the end of days, but it looks like Duke Nukem Forever is almost done. It looks like Gearbox has a working version debuting at PAX.

IGN: Duke Nukem Forever is Not Bulls--t

### DCMA Law changes

26 July 2010 - 11:02 AM

Tom's hardware - It's Now Legal to Crack Your PC Games

IGN - Smartphone Jailbreaking Deemed 'Fair Use'

Quote:
 People may now rip DVDs to show clips for educational purposes, criticism, commentary and noncommercial videos.People may now legally jailbreak their iPhones and root their Android phones without fear that a corporation will rain down upon them.People may now legally unlock their cell phones.(These first three are mostly the result of lobbying from the Electronic Frontier Foundation.)People may now circumvent the copy protection of PC and video games for investigative reasons. This should be a great thing for PC gamers sick of dealing with the DRM of the games they legally purchased.People may now get past software that's protected by an outdated hardware dongle.People may now break past ebooks that don't allow the text to be read aloud.

### Cosine Taylor Series Issue

30 June 2010 - 09:41 AM

I'm not sure if this belongs in General Programming or here.

I've been playing around with the SSE/SSE2 instructions, and have been trying to implement the calculation of cosine using the Taylor series. I've been basing my code on an article I found online, Fast Trigonometric Functions Using Intel's SSE2.

I could never quite get his ASM instructions (more of a step by step how to) to work right, but I managed to adapt the C example into an SSE2 instristic (MSVC) version. I also found that the C example he gives doesn't seem to correctly pull the input into the desired -pi/2 < x < pi/2 range, so my version is adapted from his earlier example that uses branching.

I've been running a comparison between std::cos and the results from this function and overall they tend to be pretty close. Where it starts to really break down is right around Pi.

`Input		std::cos	sse2		difference-0.983189225	0.468513191	0.468513191	0-0.883189201	0.554371059	0.554371119	-5.96E-08-0.783189178	0.634689868	0.634689868	0-0.683189154	0.70866704	0.70866704	0-0.58318913	0.775563479	0.775563479	0-0.483189136	0.834710658	0.834710658	0-0.383189142	0.885517716	0.885517716	0-0.283189148	0.927477002	0.927477002	0-0.183189154	0.960169196	0.960169196	0-0.083189152	0.983267725	0.983267725	00.016810849	0.996541798	0.996541798	00.116810851	0.999858677	0.999858677	0Input		std::cos	sse2		difference-3.683187962	-0.801142097	-0.801262379	0.000120282-3.583188057	-0.8568874	-0.857079506	0.000192106-3.483188152	-0.904070973	-0.904372096	0.000301123-3.383188248	-0.942221403	-0.942686081	0.000464678-3.283188343	-0.970957458	-0.971663117	0.000705659-3.183188438	-0.989992082	-0.991048455	0.001056373-3.083188534	-0.999135017	-1.000695705	0.001560688-2.983188629	-0.99829495	-0.999758005	0.001463056-2.883188725	-0.987480283	-0.988468528	0.000988245-2.78318882	-0.96679908	-0.967457533	0.000658453-2.683188915	-0.936457932	-0.936890245	0.000432312-2.583189011	-0.896759987	-0.897039414	0.000279427-2.483189106	-0.848101974	-0.848279595	0.000177622-2.383189201	-0.790970027	-0.791080833	0.000110805`

I believe that around Pi is where the Taylor series is no longer producing numbers close to cosine. Is there someway around this, or is there an error in my calculations?

A couple of needed constants were not in the original post.

`namespace KS{	static const __m128 PS_ZERO(_mm_setzero_ps());	static const __m128 PS_SIGN_MASK(_mm_set1_ps(-0.0f));	static const __m128 PS_ALL_MASK(_mm_cmpeq_ps(PS_ZERO, PS_ZERO));	static const __m128 PS_INV_SIGN_MASK(_mm_andnot_ps(PS_SIGN_MASK, PS_ALL_MASK));	static const __m128 PS_ONE(_mm_set1_ps(1.0f));	static const __m128 PS_PI(_mm_set1_ps(F_PI));	static const __m128 PS_1_OVER_PI(_mm_rcp_ps(PS_PI));	static const __m128 PS_PI_OVER_2(_mm_set1_ps(F_PI / 2.0f));	static const __m128i EPI32_ONE(_mm_set1_epi32(1));	static const __m128 PS_1_OVER_2FACTORIAL(_mm_set1_ps(1.0f / 2.0f));	static const __m128 PS_1_OVER_4FACTORIAL(_mm_set1_ps(1.0f / 24.0f));	static const __m128 PS_1_OVER_6FACTORIAL(_mm_set1_ps(1.0f / 720.0f));	static const __m128 PS_1_OVER_8FACTORIAL(_mm_set1_ps(1.0f / 40320.0f));	static const __m128 PS_1_OVER_10FACTORIAL(_mm_set1_ps(1.0f / 3628800.0f));	inline const float cossse(float in_Value)	{		/*	Convert input to vector	*/		__m128 _Value(_mm_set_ss(in_Value));		/*	Remove Sign	*/		_Value = _mm_and_ps(_Value, PS_INV_SIGN_MASK);		/*	Clamp the input to -Pi/2 < _Value < Pi/2	*/		/*	_Value % Pi == _Value - (Pi * static_cast<int>(_Value/Pi))	*/		__m128 _Quadrant(_mm_mul_ss(_Value, PS_1_OVER_PI));		__m128i _TruncatedQuadrant(_mm_cvttps_epi32(_Quadrant));		_Quadrant = _mm_cvtepi32_ps(_TruncatedQuadrant);		_Quadrant = _mm_mul_ss(_Quadrant, PS_PI);		_Value = _mm_sub_ss(_Value, _Quadrant);		/*	Simulate _Value = ((_Value > Pi/2) ? Pi - _Value : 0 - _Value) 	*/		_TruncatedQuadrant = _mm_add_epi32(_TruncatedQuadrant, EPI32_ONE);		_TruncatedQuadrant = _mm_srli_epi32(_TruncatedQuadrant, 1);		_TruncatedQuadrant = _mm_and_si128(_TruncatedQuadrant, EPI32_ONE);		_TruncatedQuadrant = _mm_cmpeq_epi32(_TruncatedQuadrant, EPI32_ONE);		_Quadrant = _mm_castsi128_ps(_TruncatedQuadrant);		_Quadrant = _mm_and_ps(_Quadrant, PS_PI);		_Value = _mm_sub_ss(_Quadrant, _Value);		/*	Square	*/		_Value = _mm_mul_ss(_Value, _Value);		/*	Make Negative - IEEE 754	*/		_Value = _mm_or_ps(_Value, PS_SIGN_MASK);		/*	Taylor series	*/		__m128 _Math(_mm_mul_ss(PS_1_OVER_10FACTORIAL, _Value));		_Math = _mm_add_ss(_Math, PS_1_OVER_8FACTORIAL);		_Math = _mm_mul_ss(_Math, _Value);		_Math = _mm_add_ss(_Math, PS_1_OVER_6FACTORIAL);		_Math = _mm_mul_ss(_Math, _Value);		_Math = _mm_add_ss(_Math, PS_1_OVER_4FACTORIAL);		_Math = _mm_mul_ss(_Math, _Value);		_Math = _mm_add_ss(_Math, PS_1_OVER_2FACTORIAL);		_Math = _mm_mul_ss(_Math, _Value);		_Math = _mm_add_ss(_Math, PS_ONE);		float _Out;		_mm_store_ss(&_Out, _Math);		return _Out;	}}int main(){	std::cout.precision(10);	float fValue(KS::F_PI * -2.0f);	while(fValue < (KS::F_PI * 2))	{		float fDef(std::cos(fValue));		float fSSE(KS::cossse(fValue));		float fDif(fDef - fSSE);		fValue += 0.1f;		std::cout << fValue << "\t" << fDef << "\t" << fSSE << "\t" << fDif << "\n";	}	std::cout.flush();	return 0;}`

PARTNERS