Re: [PATCH 1/6] Use LUT based implementation for (co)sine functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em Tue, 16 Dec 2014 06:41:18 +0000
"Prashant Laddha (prladdha)" <prladdha@xxxxxxxxx> escreveu:

> Antti, Mauro,
> 
> Thanks for your comments.
> 
> On 15/12/14 7:00 pm, "Antti Palosaari" <crope@xxxxxx> wrote:
> 
> 
> >On 12/15/2014 03:13 PM, Mauro Carvalho Chehab wrote:
> >> Em Mon, 15 Dec 2014 14:49:17 +0530
> >> Prashant Laddha <prladdha@xxxxxxxxx> escreveu:
> >>
> >>> Replaced Taylor series calculation for (co)sine with a
> >>> look up table (LUT) for sine values.
> >>
> >> Kernel has already a LUT for sin/cos at:
> >> 	include/linux/fixp-arith.h
> >>
> >> The best would be to either use it or improve its precision, if the one
> >>there
> >> is not good enough.
> 
> Thanks. I had not looked at this file earlier. But now when I looked at
> this file I agree with Antti¹s comments below.
> 
> 
> >
> >I looked that one when made generator. It has poor precision and it uses
> >degrees not radians.
> 
> > 
> Also, it does not support calculation for phase values falling in middle
> of two entries of LUT.
> 
> 
> >But surely it is correct practice improve existing
> >than introduce new.
> 
> I agree. Probably we can start looking into how to improve existing. I
> looked at dependancies. As of now functions in fixp-arith is used by two
> other files. Replacing current implementation in fixp-arith.h with high
> precision will not work as it is, because caller functions are using
> lesser precision. We probably need to discuss more on how to improve
> existing implementation.

if you do a:
	$ git grep -e 'sin(' --or -e 'cos('

You'll notice that there are other drivers that have also their own
sin()/cos() needs, with their own implementation.

I'm not saying we should touch them, but it is worth to check what are
their needs, in order to be sure that whatever we do would latter fit
on their usages.

> Some thoughts -
> 1. Going by the name fixp-arith.h, I feel, it should have larger scope
> than just (co)sine implementation. It can include divide as well. One
> could also consider option to keep all trignometric functions in another
> file

We could do that, but let's start with sin/cos functions. Btw, there are
log implementation functions already at dvb-core at
	drivers/media/dvb-core/dvb_math.[ch]

Those are also candidates to be moved to a more generic place.

> 2. One could support APIs to provide output with different precisions, say
> 16, 32, 64 bits etc. Not sure how final implementation would be but one
> option would be to do internal computation with highest
> precision possible and then truncate the result to have desired precision
> based on the API called.

Internally, I would stick with a 32 bits implementation, where the 1.0 would
mean S32_MAX. 64 bits is likely an overkill, and would be slower on 32 bits
machines.

Using degrees also seem to be a good thing, as the table will be symmetric,
and the 90th value will be equal to 1.0 (for a sin table). 

That means that we need an array with just 90 elements instead of 256.
To be generic enough, the logic should use modulus math, to be sure that
the given value will be converted into an angle between 0 and 360, and
then down-converted to 0-90, in order to use a table with just a quarter
of the values, e. g. something like:

static inline const s32 sin_table[] = {
	0x00000000, 0x023be165, 0x04779632, 0x06b2f1d2, 0x08edc7b6, 0x0b27eb5c, 
	0x0d61304d, 0x0f996a26, 0x11d06c96, 0x14060b67, 0x163a1a7d, 0x186c6ddd, 
	0x1a9cd9ac, 0x1ccb3236, 0x1ef74bf2, 0x2120fb82, 0x234815ba, 0x256c6f9e, 
	0x278dde6e, 0x29ac379f, 0x2bc750e8, 0x2ddf003f, 0x2ff31bdd, 0x32037a44, 
	0x340ff241, 0x36185aee, 0x381c8bb5, 0x3a1c5c56, 0x3c17a4e7, 0x3e0e3ddb, 
	0x3fffffff, 0x41ecc483, 0x43d464fa, 0x45b6bb5d, 0x4793a20f, 0x496af3e1, 
	0x4b3c8c11, 0x4d084650, 0x4ecdfec6, 0x508d9210, 0x5246dd48, 0x53f9be04, 
	0x55a6125a, 0x574bb8e5, 0x58ea90c2, 0x5a827999, 0x5c135399, 0x5d9cff82, 
	0x5f1f5ea0, 0x609a52d1, 0x620dbe8a, 0x637984d3, 0x64dd894f, 0x6639b039, 
	0x678dde6d, 0x68d9f963, 0x6a1de735, 0x6b598ea1, 0x6c8cd70a, 0x6db7a879, 
	0x6ed9eba0, 0x6ff389de, 0x71046d3c, 0x720c8074, 0x730baeec, 0x7401e4bf, 
	0x74ef0ebb, 0x75d31a5f, 0x76adf5e5, 0x777f903b, 0x7847d908, 0x7906c0af, 
	0x79bc384c, 0x7a6831b8, 0x7b0a9f8c, 0x7ba3751c, 0x7c32a67c, 0x7cb82884, 
	0x7d33f0c8, 0x7da5f5a3, 0x7e0e2e31, 0x7e6c924f, 0x7ec11aa3, 0x7f0bc095, 
	0x7f4c7e52, 0x7f834ecf, 0x7fb02dc4, 0x7fd317b3, 0x7fec09e1, 0x7ffb025e, 
	0x7fffffff
};

s32 fixp_sin32(int value)
{
	s32 ret;
	bool negative = false;

	value = (value % 360 + 360) % 360;
	if (value > 180) {
		negative = true;
		value -= 180;
	}
	if (value > 90)
		value = 180 - value;

	ret = sin_table[value];

	return negative ? -ret : ret;
}

And then define the 16 bits and cos() variants for it with:

#define fixp_cos32(v) fixp_sin32((v) + 90)
#define fixp_sin16(v) (fixp_sin32(v) >> 16)
#define fixp_cos16(v) (fixp_cos32(v) >> 16)

If we end latter to need 64 bits, it shouldn't be hard to change
the logic there to add a different table.

Regards,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux