deftio / fr_math

Fixed Radix Math library for embedded systems (opt for speed)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect FR_FIXMUL32u

dwilliss opened this issue · comments

I was trying to use this to write a fixed-point mandelbrot set program to run on a GPU using the CUDA Toolkit. The results were interesting but wrong.

image

Zooming in on that dot in the center gives this cool image:
image

Anyway, the culpret turned out to be that the 4th term needed a right shift by 16

#define FR_FIXMUL32u(x,y)	(					\
	(((x>>16)*(y>>16))<<16)+					\
	((x>>16)*(y&0xffff))+						\
	((y>>16)*(x&0xffff))+						\
	((((x&0xffff)*(y&0xffff)))>>16)					\
	)

After that, everything looked correct.
image

This was with 15.16 fixed. Since the magnitude of the numbers is so low, I tried 4.27 hoping to get better precision as I zoomed in. Instead I got this.
image
I'm not sure what's wrong here yet, but if I zoom in 1200x on that right circle...
image

Ok I'll take a look!

FYI, I did some math and trying to multiply this way with .27 just causes the first term to overflow. But for .16 numbers it works great.

I came up with a nice optimization for squaring a number. You only have to take the ABS once and you can ignore the sign of the output since it will always be positive.

// Square can be simplified since it's one number and the result must be positive
__device__ inline int FR_Square(int x) {
	x = FR_ABS(x);
	return FR_FIXMUL32u(x, x);
}

OK good find. I updated the FR_FIXMUL32 macro.

I added FR_SQUARE but as a macro. The reason for that instead of inline, is there is an old project on an embedded system that is using C99 support. This should give the same effect though.

Much thanks for your contribution!