Sháním: Knihovna pro AVR FloatingPoint (BSD / LGPL licence)

Zdravím, chtěl bych se zeptat , jestli někdo neznáte nějakou assemblerovskou knihovnu pro výpočty v plovoucí řádové čárce. Případně i pro pevnu řádovou čárku.

Ideální by byla BSD licence , nebo LGPL

Děkuji za info , Martin.

:arrow_right: administrator: přejmenováno z "Knihovna pro AVR FloatingPoint"

Celočíselný jsou v app notes na webu atmelu. Float jsem nehledal, vždy jsem se bez toho zatím obešel.

Celočíselný bych měl dát dohromady i z hlavy tak za den :smiley: Chtěl bych to víceméně kvůli studiu. Vrtat se v knihovnách z céčka se mi moc nechce.

Tak mě napadá. ten fixed point se dá vyřešit celočíselně, jen to ponásobím stovkou a mám dvě místa…

Ach ta hlava …

Ta celočíselná aritmetika v aplikačních poznámkách je v asm.
S pevnou ř. čárkou se to dělá přesně jak píšeš :slight_smile:
Později, až ti něco nebude stíhat, dojdeš i na to, že je vhodný upravit výpočty pro dvojkovou soustavu - např. místo procent 1/100 použít 1/128 a zvýšit základ. Výsledek je pak stejný jako u procent, jen výpočet je rychlejší.

Právě tenhle binární způsob mě trochu děsil , jako že nemám 0.2 ale třeba 0.256 takže potom převod, třeba na znaky pro USART bude (pro mně) hůř pochopitelnej. Tyhlety soustavy, to není zrovna můj šálek kávy, ale co , bojovat se musí .

Celočíselně sčítat a odčítat by měl bejt minimální problém , každopádně kouknu do těch aplikačních poznámek, případný rozšíření třeba na 64 bitů by taky mohlo jít celkem snadno .

Díky moc za nakopnutí.

Ten převod na znaky je ještě jednodušší než u integeru. Když máš např. číslo 0b01000000 reprezentující hodnotu 0,25 převést na znaky, uděláš to postupným násobením 10 instrukcí MUL. V horním byte dostaneš dekadickou cifru za desetinou čárkou a v dolním zbytek, který opět vynásobíš 10. Tímto postupem získáš postupně všechny cifry od nejvyšších řádů až po nejnižší.
Pokud by si chtěl algoritmus na float, není nic jednoduššího než založit projekt v Céčku, napsat jediný řádek s operací float, přeložit a podívat se do listu na výsledek v asm.

Dobře, prozkoumám to.
ASM je mi bližší než C , ani nevím proč, možná proto, že jsem v něm kdysi sem tam něco dělal na ZX Spectru , dokonce i něco jako multitasking. Je mi jasné, že v céčku se vyvíjí rychleji ale když jsem našel jeden příklad pro řízení spínaného zdroje a kód v C měl po přeložení cca 1kB a v ASM asi 400 B byl jsem překvapen a to tak, že hodně , vždycky jsem myslel, že C bude hodně optimalizované a výsledek bude ± podobný.

No a ak zoberies 1/256, potom je rozhranie cela cast a desatinna cast prave medzi dvoma bajtmi.

Takže jestli tomu dobře rozumím tak v tom případě : 00000001 00000001 =1,00390625 a 11111111 00000011 =255,01171875 ?

Na matyku jsem niky moc kádr nebyl :smiley:

Naprosto správně :slight_smile:

Tak to teda bude něco, než to pochopím, myslel jsem, že to udělám ve stylu 255 = 2.55 65535=655.35 :slight_smile:

Takže tímhle způsobem je 00000000 11111111 něco kolem 0.99 ? Tahle přesnost by mi stačila, pro počítání budu muset použít 24 bitů .

Sčítání a odčítání je mi jasný , násobení celkem taky , převod na znaky snad podle Technika pochopím. Jdu na test.

00000000 11111111b = 0 + 12^(-1) + 12^(-2) + 12^(-3) + … + 12^(-8 ) = 1 - 1*2^(-8 ) = 0.99609375
Stále to máš dobře :wink:
Násobení už tak jednoduchý nebude, nemysli si :smiley:

Ale jo , jednoduchý bude , ale ne z nejrychlejších přičítáme pořád dokola :slight_smile:

Nebo posun doleva tolikrát , kolik je nejbližší násobek 2 + případně přičíst ještě jednou ?

Tak obyčejnej posun to nebude …

Co je na něm tak složitého? Číslo, které jsi uvedl, můžeš zapsat jako 0x00FF2^(-8). Vynásobím např. 2, kterou mohu zapsat takto: 0x02002^(-8). Jde o exponenciální tvar, kde platí, že při násobení se násobí mantisy a exponenty se sčítají.

0x00FF2^(-8) * 0x02002^(-8) = 0x0001FE002^(-16) = 255512*2^(-16)

0x00.FF * 0x02.00 = 0x0001.FE00

Exponent 2 představuje pozici binární tečky se kterou se u fixed point nemusíme zabývat, takže celé násobení je úpně totožné jako u (unsigned) int. Pozice binární tečky je rozhodující pouze při převodu do dekadické soustavy.
Pro zajímavost: exponent nemusí být vždy 2, může to být zcela libovolné číslo, třeba Ludolfovo. Klidně i 10. Na tom pak bude záležet i numerická přesnost. Né každé číslo lze zapsat, takže se musí zaokrouhlovat na nejbližší.
Jako příklad uvedu deklaraci proměnné H, která bude reprezentovat vzálenost s přesností na 0,001 m. Nepotřebuji floating ani fixed point, stačí zapsat:

unsigned int H; // vzdálenost v mm

Mohu ji zrovna tak interpretovat jako H*10^(-3) v metrech. Takže je to jen záležitost převodu do dek. soustavy.
Nevím, zda v Céčku existuje fixed point, ale z výše uvedeného je zřejmé, že by byl zcela zbytečný a v pohodě jej nahradí int.

Myslím, že piityy měl na mysli, že řešení násobení n-bitového čísla v ASM nebude pro mně , jako pro začátečníka tak jednoduchý, jak si myslím, že je .

Tak… A ernie má po zábavě. Takovej krásně dlouhej a pomalej podprogram mohl vytvořit a nic z toho nebude :smiley: Teď jen upraví uint16*uint16 a je hotovo.

V C to není, taky to vždy řeším dostatečně dimenzovaným uint.
Za určitých okolností by se mu mohl snížit dopad ořezávání, protože bude odstraňovat pouze 1 msB (a 1 lsB) místo dvou msB u intu, jinak to ale asi žádný zvláštní význam nemá.

Hmm. Moc dlouho jsem do toho vejral, ernie byl rychlejší :slight_smile:

Pomalý to vytvořím tak jako tak , jinak by to byla celkem nuda :slight_smile:

Stáhni si aplikační poznámku AVR200. Už je to tam naprogramovaný. Můžeš si i vybrat, zda chceš maximální rychlost/minimální velikost.

Po násobení dvou 2B čísel ti vyjde jedno 4B. Nejvyšší a nejnižší byte zahodíš, prostředek je tvůj výsledek. Z Technikova postu to přímo svítí :smiley: