How to quickly check if a block of memory is zero?

Started by
12 comments, last by JackOfAllTrades 13 years, 4 months ago
I wrote a function that worked beautifully in python but now I'm trying to convert it to C++. I'm having a problem since in python a list item can be none but the closest thing to this I can do in C++ is check if the item in the vector is zero though it's not perfect it's all I can do.

Basically I have a class that has a few floats in it and I need to check if all the floats are set to zero but I don't want to have to check each variable individually. Is there a way to check if all bits in a block of memory are zero?
Advertisement
Nope.

But why not clear() the vector, which will remove all of the contents - which probably amounts to the same thing as "none".
Quote:Original post by Evil Steve
Nope.

But why not clear() the vector, which will remove all of the contents - which probably amounts to the same thing as "none".


This is going to be complex but I'll try to explain what I am doing. I'm trying to get a mesh from the FBX SDK but the mesh data is not stored in raw vertices and indices, however, it is stored very similar to the way blender stores it's mesh data so I am trying to take the code from my old export plugin for blender and convert it to C++ to use with the FBX SDK.

This script gets each polygon and checks the vertices that it is indexing. It compares them to the vertices that are already in the list so that if the face vertex does not match the vertex in the list it will create a new vertex for that face and alter the indices accordingly.

Here it is in C++:

			int ControlPointCount = FBXMesh->GetControlPointsCount();			KFbxVector4* ControlPoints = FBXMesh->GetControlPoints();			std::vector<AxVertex> vertices;			std::vector<AxFace> faces;			std::vector<int> attributes;			vertices.resize( ControlPointCount );			for( int p = 0; p < FBXMesh->GetPolygonCount(); p++ )			{				int indices[3];				for( int i = 0; i < FBXMesh->GetPolygonSize(p); i++ )				{					int vi = FBXMesh->GetPolygonVertex( p, i );					AxVertex vertex = {0};					KFbxVector4 normal;					FBXMesh->GetPolygonVertexNormal( p, i, normal );					vertex.x = ControlPoints[vi][0];					vertex.y = ControlPoints[vi][1];					vertex.z = ControlPoints[vi][2];					vertex.nx = normal[0];					vertex.ny = normal[1];					vertex.nz = normal[2];					if( vertices[vi] != vertex || vertices[vi] == 0)// Needs to check if the vertex is zero here and the == 0 does not work.					{						vertices.push_back( vertex );						indices = vertices.size() - 1;					}					else					{						vertices[vi] = vertex;						indices = vi;					}				}				if(FBXMesh->GetPolygonSize(p) == 4)				{					AxFace face;					face.indices[0] = indices[0];					face.indices[1] = indices[2];					face.indices[2] = indices[3];					faces.push_back( face );					attributes.push_back(FBXMesh->GetPolygonGroup(p));				}				AxFace face;				face.indices[0] = indices[0];				face.indices[1] = indices[1];				face.indices[2] = indices[2];				faces.push_back( face );				attributes.push_back(FBXMesh->GetPolygonGroup(p));			}


The problem with this is that the vector items are all zeroed out so when it compares a vertex to a vertex in the vector it never matches since the vector items are all zero. I want to check if a vertex in the vector is zero so I can tell it to just replace them instead of creating a new vertex.

Now I could of course just copy the vertices from the mesh into my list but they are all stored as doubles and I would need to do a bunch of other stuff to get the normals, UVs, and other data needed. I would essentially be doing the same thing twice which would be a complete wast.
Question; why not just use the python to sort out the data anyway?

You already have the code so re-doing it in C++ seems like a waste, and given that a game should only be loaded native formats anyway, which shouldn't need mucking about with at load time, this should be an 'off line' processso the speed of processing isn't really a problem.
if(vec.end() != find_if(vec.begin(),vec.end(), NotEqualtoZero))
{
Something is not equal to zero.
}

is one approach. Note the previous approach checks each value individually and you would have to write NotEqualtoZero yourself.

A sillier yet closer to what you asked for approach would be.

char* myptr = malloc(sizeofblock);
memset(myptr,0,sizeofblock);
if(0 != memcmp(myptr, memblockToCompare, sizeofblock))
{
Something is not zero.
}

note this only works if your float zero is actually zeroed bytes. This may not be true(the floating point standard has the idea of negative zero).
Quote:Original post by phantom
Question; why not just use the python to sort out the data anyway?

You already have the code so re-doing it in C++ seems like a waste, and given that a game should only be loaded native formats anyway, which shouldn't need mucking about with at load time, this should be an 'off line' processso the speed of processing isn't really a problem.


FBX is an intermediate format which will allow any modeling application that supports the FBX format to export models to my engine instead of me having to write an exporter for each individual modeling application. After the mesh is loaded from the FBX file into my native class it can easily be saved to a native format through the class's save function.
Well I'm just comparing it to a zeroed out vertex and it works fine for my use.
This might require some modification.

// ---------------------------------------------------------------------------/*// a wonderful little snippet for checking 4 bytes in 3 cycles#define has_nullbyte_(x) ((x - 0x01010101) & ~x & 0x80808080)movl %eax, %edx         ; cycle 1not  %eaxsubl $0x01010101, %edx  ; cycle 2andl $0x80808080, %eaxandl %edx, %eax         ; cycle 3// inline*/BOOL __declspec(naked) _stdcall CheckNullBytes(void *address){    _asm(        "movl   4(%esp),%eax;      \n" // argument        "movl   %eax, %edx;        \n" // cycle 1        "not    %eax;              \n" //        "subl   $0x01010101, %edx; \n" // cycle 2        "andl   $0x80808080, %eax; \n" //        "andl   %edx, %eax;        \n" // cycle 3        "ret    $4;                \n" //    );}


I found this via Paul Hsieh, Assembly Language Lab. Scroll down about half way through the page or search for "old trick". YMMV.

Alternatively, if you want all the bits in the block to be zero, just use memset on them and be done with it.

// edit

A variation on the has null byte check can be found here: Fast strlen function. Search for "Brian Hurt, 2 years ago".

// You can detect a null in a four-byte word like:    unsigned y = x & 0x7F7F7F7Fu;    y += 0x7F7F7F7F;    y |= x;    if ((y & 0x80808080) != 0x80808080u) {        /* x has a nul- check each byte */    } else {        /* x does not have a null */    }/* The advantage this approach has is fewer jumps- and it uses only simple (1-clock) instructions, and 2 registers- allowing you to unroll this loop 2 or 3 times and give the execution units plenty to do.*/


[Edited by - LessBread on December 20, 2010 10:34:22 PM]
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Be careful with floats though; there is such a thing as "minus zero."
I don't get the code posted. You are resizing a vector to accomodate point data and then you are growing it with that same data.

Why not just do something along those lines:

int ControlPointCount = FBXMesh->GetControlPointsCount();KFbxVector4* ControlPoints = FBXMesh->GetControlPoints();std::vector<AxVertex> vertices;std::vector<AxFace> faces;std::vector<int> attributes;std::vector<int> indicesMap(ControlPointCount, -1);for( int p = 0; p < FBXMesh->GetPolygonCount(); p++ ){	int indices[3];	for( int i = 0; i < FBXMesh->GetPolygonSize(p); i++ )	{		int vi = FBXMesh->GetPolygonVertex( p, i );		AxVertex vertex = {0};		KFbxVector4 normal;		FBXMesh->GetPolygonVertexNormal( p, i, normal );		vertex.x = ControlPoints[vi][0];		vertex.y = ControlPoints[vi][1];		vertex.z = ControlPoints[vi][2];		vertex.nx = normal[0];		vertex.ny = normal[1];		vertex.nz = normal[2];				if (indicesMap[vi] == -1)		{			int vertexIdx = vertices.size();			vertices.push_back(vertex);			indices = vertexIdx;			indicesMap[vi] = vertexIdx;		}		else		{						indices = indicesMap[vi];		}				}	if(FBXMesh->GetPolygonSize(p) == 4)	{		AxFace face;		face.indices[0] = indices[0];		face.indices[1] = indices[2];		face.indices[2] = indices[3];		faces.push_back( face );		attributes.push_back(FBXMesh->GetPolygonGroup(p));	}	AxFace face;	face.indices[0] = indices[0];	face.indices[1] = indices[1];	face.indices[2] = indices[2];	faces.push_back( face );	attributes.push_back(FBXMesh->GetPolygonGroup(p));}


[Edited by - alagtriste on December 20, 2010 3:11:04 PM]

This topic is closed to new replies.

Advertisement