How to code and use commonly used algorithms

Started by
65 comments, last by Nice Coder 19 years, 2 months ago
Quote:
char * c = (char *)number; // (*)
if (c[3]) {
Return (LogTable256[c[3]] + 20); // (***)
}
if (c[2]) {
Return (LogTable256[c[2]] + 16);
}
if (c[1]) {
Return (logTable[c[1]] + 8);
}
Return (logtable[c]); // (**)


The above code is wrong because:

(*) : you are assuming things about the endian-ness of your numbers. For instance, a number that you write as 0x12345678 can be stored in memory as [0x34][0x12][0x78][0x56]. You have no way to know the endian-ness of your integers (aside from platform-specific compiling alteration), so casting to a char* and testing the bytes will only work by sheer luck.

(**) : c will usually have a very high value, since it's a pointer. You will therefore overflow logtable[].

Edit (***) : this should be 24.

[Edited by - ToohrVyk on January 31, 2005 1:33:44 AM]
Advertisement
While you're at it, what's the fastest way to determine if two lines of finite length, in 2d space, intersect?
Check if the two endpoints of each line lie on different sides of the other line.
A simple combination lock, for cryptography.

Usage: You take the number, and use that to generate a key to encrypt/decrypt data. You can use this to make a safe, where users can safely store there files.

Keys (should be randomly generated)
int128 combinations[NUM];int256 modkey;

NUM is the number of combinations in the key, more is better, but harder to use.

Complexity is (If you have all of the keys, it is much greater otherwise) KEYS^NUM. So, if you have 18 keys (0-9, A-F, # and *), and 12 digits in the combination, there are 1,156,831,381,426,176 combinations. That is if you have the key.

Now, if you don't know the keys, you basically have to check 2^256 different mods, as well as (2^128)^Num
Leaving (2^128)^num * 2^256
Which is massive.
Very massive.
It is about
279095111627852376407822673918065072905887935345660252615989519488029661278604994789701101367875859521849524793382568057369148405837577299984720398976429790087982805274893437406788716103454867635208144157749912668657006085226160261808841484862703257771979713923863820038729637520989894984676774385364934677289947762340313157123529922421738738162392233756507666339799675257002539356619747080176786496732679854783185583233878234270370065954615221443190595445898747930123678952192875629172092437548194134594886873249778512829119416327938768896

Now, you are not going to check that many keys anytime soon.

Code:
int256 combination;for x = 0 to NUMcombination += INPUTDIGIT * combinations[x];combination %= modkeynext x// Combination is now your key.


It is simple, yet quite effective.

I'm probably going to write an application to run safes like these. Which doesn't store the actual values with itself, so you could say email someone a safe, keep the combination file inside a flashdisk, and know that nobody is ever going to get the combination. Especially if you have a very long combination. a 12 digit combination is fine, as it has about a quadrillion possible combinations. You could use a slightly longer key, and the number of combinations skyrockets.

:)

But of cource its limited by how bit modkey is.
The output number, has only modkey combinations, which means that at most, it will take modkey attempts.
But then again, modkey would be randomly generated, and basically guarenteed to be huge (and for those who don't have the keyfile, impossible to determine).

Its not like integer factorisation (see RSA), where at most you have to check sqrt(n), you have to check half of N on average.

Thats 2^255 or only about
57896044618658097711785492504343953926634992332820282019728792003956564819968


Which is also very very very massive.

If you have a long enough key, then you end up with the number of combinations being dwarfed by the number of posisble keys (modkey).

From,
Nice coder

[Edited by - Nice Coder on February 5, 2005 6:42:48 PM]
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
Quote:Original post by Nice Coder
How to map degrees to a value from 0 to 359.

inline int wrap(int degrees)
{
//filter all numbers to be from 0 to 359.
degrees &= 511; //Strip off every bit after the ninth one. (ie. Mod it by
512)
if (degrees > 359) {Degrees -= 359;} //If degrees is too big, make it fit.
Now that degrees can only be from 0-512, this always returns the correct value.
return degrees; //Return the new value.
}
That doesn't work, nor does your later version. Almost every value greater than 511 will be incorrect. You can't simply mask off the upper bits because 512 is not a multiple of 360.
Quote:So, as an actual mod replacement package:

inline int32 mod(int32 number, int32 modw)
{
int32 npo = modw - 1;
npo |= npo >> 1;
npo |= npo >> 2;
npo |= npo >> 4;
npo |= npo >> 8;
npo |= npo >> 16;
number &= (npo + 1);
int32 ndeg = (number - modw);
int32 max = ndeg >> 31;
return (ndeg & max) + (number& ~max);
}
Nope, just like your above code, that also doesn't work for pretty much the same reasons.
Quote:Sqrt += (num & 2) >> 1;
Sqrt += (num & 4) >> 2;
Sqrt += (num & 8) >> 4;
Sqrt += (num & 16) >> 8;
Sqrt += (num & 32) >> 16;
... //And so on, for the rest of the powers of two.

And it works two!
No, again that's just you thinking out loud, and has no resemblance to any correct method for calculating the square root.

Here is the correct integer square root function:
inline long isqrt(unsigned long x) {	register unsigned long r, nr, m;	r= 0;	m= 0x40000000;	do {		nr= r + m;		if (nr<=x) {			x-= nr;			r= nr + m;		}		r>>= 1;		m>>= 2;	} while (m!=0);	if (x>r) r+= 1; //This line rounds the answer	return r;}
I can't remember where it comes from though.

You should have quit while you were ahead. Most of what you've been posting in this thread of late, is very very wrong. Please test throughly before you post.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
ok, i have no idea how i managed to think that those actually worked.....

The square root method returns an approximate square root, with a bit of error.

It is workable, and can be used as a guess for a more exact version.

Will someone please tell me when something doesn't work? (like imalc, thanks.)

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
Try this one.

A simple array based stack.

On pop, you get the data that is in the current slot in the array (it is pointed to by sp) Before decrementing your stack pointer.

This should be simple enough, maybe something like return x, *x++ ?

on push, you go and you change the value that is currently pointed to by the stack pointer, becore incrementing the stack pointer.

Maybe something like x = y; *x++ ?
Of cource you should check that you are not going out of bounds, but have unchecked version (inlined of cource) for people who really like speed.

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.

This topic is closed to new replies.

Advertisement