www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - recursive template (first attempt)

reply akcom <CppCoder gmail.com> writes:
I apologize if this is an easily resolved problem, this is my first
attempt at writing a template function.  the objective of this function
is to mimic the behavior of the AP hash function, but as a template
function obviously.  Here is what I have so far:

uint aphash( ubyte []buf )
{
	uint hash;
	
	for ( uint i = 0; i < buf.length; i++ )
	{
		hash ^= ((i & 1) == 0) ?	(  (hash <<  7) ^ (buf[i]) ^ (hash >> 3)) :
									(~((hash << 11) ^ (buf[i]) ^ (hash >> 5)));
	}
	return hash;
}

template aphasht( T : ubyte [] )
{
	uint aphasht( T t )
	{
		uint result;
		static if ( t.length == 0 )
		{
			return 0;
		}
		static if ( t.length & 1 )
		{
			result = aphasht( t[1..$] );
			return (result << 7) ^ t[0] ^ (result >> 3);
		}
		else
		{
			result = aphasht( t[1..$] );
			return (result << 11) ^ t[0] ^ (result >> 5);
		}
	}
}

void test()
{
	static ubyte []str = [ 0x01, 0x02, 0x03, 0x03 ];
	writefln( "aphash(str) = %X", aphash( str ) );
	writefln( "aphasht(str) = %X", aphasht!(ubyte [])( str ) );
}


When I attempt to compile it, I get the following errors:

dmd -w -c main.d
main.d(49): expression ((t).length) == 0u does not evaluate to a boolean
main.d(53): expression ((t).length) & 1u does not evaluate to a boolean
main.d(70): template instance main.aphasht!(ubyte[]) error instantiating

Could someone please point out my mistake, and if there is a more
elegant way of completing this task, I'd appreciate some input on that
as well.

Regards,
Alex
Apr 19 2006
parent reply Ryan Steen <Ryan_member pathlink.com> writes:
In article <e26v01$2m8$1 digitaldaemon.com>, akcom says...

		static if ( t.length == 0 )
		static if ( t.length & 1 )
main.d(49): expression ((t).length) == 0u does not evaluate to a boolean
main.d(53): expression ((t).length) & 1u does not evaluate to a boolean

"It is an error if AssignExpression ... cannot be evaluated at compile time."
Apr 19 2006
parent reply akcom <CppCoder gmail.com> writes:
Ryan Steen wrote:
 In article <e26v01$2m8$1 digitaldaemon.com>, akcom says...
 
 
		static if ( t.length == 0 )
		static if ( t.length & 1 )
main.d(49): expression ((t).length) == 0u does not evaluate to a boolean
main.d(53): expression ((t).length) & 1u does not evaluate to a boolean

"It is an error if AssignExpression ... cannot be evaluated at compile time."

Apr 20 2006
parent reply Don Clugston <dac nospam.com.au> writes:
akcom wrote:
 Ryan Steen wrote:
 In article <e26v01$2m8$1 digitaldaemon.com>, akcom says...


 		static if ( t.length == 0 )
 		static if ( t.length & 1 )
 main.d(49): expression ((t).length) == 0u does not evaluate to a boolean
 main.d(53): expression ((t).length) & 1u does not evaluate to a boolean

"It is an error if AssignExpression ... cannot be evaluated at compile time."


It's just because array literals are only supported at this time for strings. (Your code might work in DMD 2.0). If you change the definitions to const char [] str = x"01 02 03"; template aphasht( char [] T) { const uint aphasht = ... } (changing returns to const aphasht). it would work with writefln( "aphasht(str) = %X", aphasht!(str ) );
Apr 20 2006
parent akcom <CppCoder gmail.com> writes:
Don Clugston wrote:
 akcom wrote:
 
 Ryan Steen wrote:

 In article <e26v01$2m8$1 digitaldaemon.com>, akcom says...


         static if ( t.length == 0 )
         static if ( t.length & 1 )
 main.d(49): expression ((t).length) == 0u does not evaluate to a
 boolean
 main.d(53): expression ((t).length) & 1u does not evaluate to a boolean

"It is an error if AssignExpression ... cannot be evaluated at compile time."


It's just because array literals are only supported at this time for strings. (Your code might work in DMD 2.0). If you change the definitions to const char [] str = x"01 02 03"; template aphasht( char [] T) { const uint aphasht = ... } (changing returns to const aphasht). it would work with writefln( "aphasht(str) = %X", aphasht!(str ) );

I finally got it working, but for some odd reason the templates gives different results than the original function when the string being processed has a length that is odd, any ideas? uint aphash( char []buf ) { uint hash; hash = 0; for ( uint i = 0; i < buf.length; i++ ) { hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (cast(ubyte)buf[i]) ^ (hash
 3)) :


} return hash; } template aphashT( char []s, uint lastHash = 0 ) { static if ( s.length == 0 ) { const aphashT = lastHash; } else static if ( s.length & 1 ) { const aphashT = aphashT!( s[1..$], lastHash ^ ~( (lastHash << 11) ^ cast(ubyte)(s[0]) ^ (lastHash >> 5) ) ); } else { const aphashT = aphashT!( s[1..$], lastHash ^ ( (lastHash << 7) ^ cast(ubyte)(s[0]) ^ (lastHash >>3) ) ); } } unittest { assert( aphashT!( "aaa" ) == aphash( "aaa" ) ); //fails assert( aphashT!( "abcdefg12345" ) == aphash( "abcdefg12345" ) ); assert( aphashT!( "rofl haxor" ) == aphash( "rofl haxor" ) ); assert( aphashT!( "abc" ) == aphash( "abc" ) ); assert( aphashT!( "hello world" ) == aphash( "hello world" ) ); //fails }
Apr 20 2006