Fixed point-problem
Re: Fixed point-problem
> Hur man skulle hantera 16.16 x 16.16 var bara ett exempel på ett ställe där man måste
> hantera det på något sätt. Kör man bara rätt av med multiplikation så tappar du ju
> så att säga bort hela heltalsdelen.
Japp, men fortfarande ingen som helst skillnad mot en vanligt integer 32x32 multiplikation.
Det är just det som är poängen. Det är i princip samma "hantering". Om de lägsta 16 bitarna
av de 32 bitarna representerar de 16 lägsta heltalsbitarna eller 16 decimalbitar spelar
igentligen ingen som helst roll, man måste fortfarande ta i princip samma beslut kring
hur resultatet ska hanteras och tolkas.
> ifall man inte kan ta resultatet från en multiplikation och använda denna precis som vilket annat tal som helst.
Så är det ju alltid. Hur ska du ta 64 bitars resultatet från en vanlig integer 32x32 mult och
använda det "som vilket annat tal som helst" ?? Och vad *är* "vilket annat tal som helst" ?
> Dessutom måste blir det antagligen överslag efter några få operationer ifall man inte skiftar
> ner och trunkerar bort lägsta bitarna.
Självklart, men det har ingenting med fixed point att göra, så är det vid all multiplikation.
> hantera det på något sätt. Kör man bara rätt av med multiplikation så tappar du ju
> så att säga bort hela heltalsdelen.
Japp, men fortfarande ingen som helst skillnad mot en vanligt integer 32x32 multiplikation.
Det är just det som är poängen. Det är i princip samma "hantering". Om de lägsta 16 bitarna
av de 32 bitarna representerar de 16 lägsta heltalsbitarna eller 16 decimalbitar spelar
igentligen ingen som helst roll, man måste fortfarande ta i princip samma beslut kring
hur resultatet ska hanteras och tolkas.
> ifall man inte kan ta resultatet från en multiplikation och använda denna precis som vilket annat tal som helst.
Så är det ju alltid. Hur ska du ta 64 bitars resultatet från en vanlig integer 32x32 mult och
använda det "som vilket annat tal som helst" ?? Och vad *är* "vilket annat tal som helst" ?
> Dessutom måste blir det antagligen överslag efter några få operationer ifall man inte skiftar
> ner och trunkerar bort lägsta bitarna.
Självklart, men det har ingenting med fixed point att göra, så är det vid all multiplikation.
Re: Fixed point-problem
Jag kan inte annat än hålla med. Men jag misstänker att du missar lite poängen här.
Har du en funktion som beräknar säg multiplikation mellan två 16.16 operander och spottar ut en 16x16 så vet du att oavsett hur du gör så har du lika stor heltalsdel som decimaldel.
Det går ju bra att "hur som helst" multiplicera tal oavsett vilken notation du har, men när du ska ha det till nåt, då blir det lurigt ifall du inte vet vad du har.
Har du en funktion som beräknar säg multiplikation mellan två 16.16 operander och spottar ut en 16x16 så vet du att oavsett hur du gör så har du lika stor heltalsdel som decimaldel.
Det går ju bra att "hur som helst" multiplicera tal oavsett vilken notation du har, men när du ska ha det till nåt, då blir det lurigt ifall du inte vet vad du har.
Re: Fixed point-problem
Om man bara har definierat _ett_ fixed format så kan man ju inte låta t.ex. 4.12x4.12 bli 8.24 bitar. Även om man multiplicerar 4.12x4.12 så vill man kanske ha 4.12 ut också.sodjan skrev: Japp, men fortfarande ingen som helst skillnad mot en vanligt integer 32x32 multiplikation.
Det är just det som är poängen. Det är i princip samma "hantering". Om de lägsta 16 bitarna
av de 32 bitarna representerar de 16 lägsta heltalsbitarna eller 16 decimalbitar spelar
igentligen ingen som helst roll, man måste fortfarande ta i princip samma beslut kring
hur resultatet ska hanteras och tolkas.
Och ja, det ökar såklart risken för overflow, och ja, man får avrundningsfel. Men det är ju kända konsekvenser som man måste vara medveten om när man räknar med fixed.
Det första (overflow) ju exakt samma problem som du får om du multiplicerar en int med en int och stoppar in resultatet i en int.
Re: Fixed point-problem
> Om man bara har definierat _ett_ fixed format...
"Om man bara har definierat _ett_ integer format..."
Ja, exakt hur gör man då ??
> ...så kan man ju inte låta t.ex. 4.12x4.12 bli 8.24 bitar. Även om man multiplicerar
> 4.12x4.12 så vill man kanske ha 4.12 ut också.
Vilket är samma sak som att säga :
"...så kan man ju inte låta t.ex. 16x16 bitar bli 32 bitar. Även om man multiplicerar
16x16 så vill man kanske ha 16 ut också."
Problemet är att 4.12 x 4.12 *blir* just 8.24 (om man vill kunna representera alla
tänkbara invärden och resultat). Det är ju just det som man måste "hantera", som det
har beskrivits tidigare i tråden. Och *min* poäng är att det är, i princip, samma hantering,
överväganden och effekter oavsett var man väljer att placera decimalkommat. T.ex i slutet
(en vanlig heltals int) eller någonstans mitt inne i talet (fixed point).
Ingen, enda skillnaden på en "vanlig" int och en "fixed point" är placeringen av
decimalkommat. Även en heltals int är en "fixed point" med kommat på slutet...
Aja, det framgår fortfarande inte vad "fMul()" gör utöver vad den vanlig int mult gör.
"Om man bara har definierat _ett_ integer format..."
Ja, exakt hur gör man då ??
> ...så kan man ju inte låta t.ex. 4.12x4.12 bli 8.24 bitar. Även om man multiplicerar
> 4.12x4.12 så vill man kanske ha 4.12 ut också.
Vilket är samma sak som att säga :
"...så kan man ju inte låta t.ex. 16x16 bitar bli 32 bitar. Även om man multiplicerar
16x16 så vill man kanske ha 16 ut också."
Problemet är att 4.12 x 4.12 *blir* just 8.24 (om man vill kunna representera alla
tänkbara invärden och resultat). Det är ju just det som man måste "hantera", som det
har beskrivits tidigare i tråden. Och *min* poäng är att det är, i princip, samma hantering,
överväganden och effekter oavsett var man väljer att placera decimalkommat. T.ex i slutet
(en vanlig heltals int) eller någonstans mitt inne i talet (fixed point).
Ingen, enda skillnaden på en "vanlig" int och en "fixed point" är placeringen av
decimalkommat. Även en heltals int är en "fixed point" med kommat på slutet...
Aja, det framgår fortfarande inte vad "fMul()" gör utöver vad den vanlig int mult gör.
Re: Fixed point-problem
Jag förstår inte vad diskussionen går ut på.
Det är inte fixpunkt ifall man flyttar kommat, det är ju det som är hela grejen.
Skillnaden mot att multiplicera två heltal, med formaten 16.0 x 16.0 om man så vill, är att kommat faktiskt inte flyttar på sig. Det tänkta kommat är fortfarande placerat före bit 0.
T.ex. så skulle en 10.6 x 10.6 multiplikationsrutin se ut på följande sett:
eller:
Eller någon kombination av dessa beroende på vad man prioriterar.
Det är inte fixpunkt ifall man flyttar kommat, det är ju det som är hela grejen.
Skillnaden mot att multiplicera två heltal, med formaten 16.0 x 16.0 om man så vill, är att kommat faktiskt inte flyttar på sig. Det tänkta kommat är fortfarande placerat före bit 0.
T.ex. så skulle en 10.6 x 10.6 multiplikationsrutin se ut på följande sett:
Kod: Markera allt
u16 fixmult( u16 fix1, u16 fix2 ) {
u32 res = (fix1 * fix2) >> 6;
return (u16)res;
}
Kod: Markera allt
u16 fixmult( u16 fix1, u16 fix2 ) {
u16 res = (fix1 >> 3) * (fix2 >> 3);
return res;
}
Re: Fixed point-problem
Som det är sagt så multiplicerar jag 2st 32 bitars integers och får ett 64bitars svar som sedan skiftas för att få rätt storlek och format.
Kod: Markera allt
fixed fMul(fixed a, fixed b)
{
return (fixed)(((int64_t)a * b) >> FRAC_PART);
}
fixed fDiv(fixed a, fixed b)
{
return (fixed)(((int64_t)a << FRAC_PART) / b);
}
Re: Fixed point-problem
Jo, jag tror att vi nog är ganska överens igentligen... 
Med andra ord, en fMul() rutin blir bara meningsfull om
den *förutsätter* ett visst fixed point format, t.ex "10.6".
D.v.s så att den kan ha de nödvändiga justeringarna av
formatet inbyggt.
Multiplikationer är alltid besvärliga när man vill ha tillbaka
resultatet i samma format. Vad gör man med overflow ?
Båda dina exempel drabbas enkelt av det med bara marginellt
för stora värden på fix1 och fix2.
Korkens kod kom just in. Och den har så klart samma begränsningar
i värderna på de ingående variablerma. Ganska naturligt. För övrigt
så fungerar det.

Med andra ord, en fMul() rutin blir bara meningsfull om
den *förutsätter* ett visst fixed point format, t.ex "10.6".
D.v.s så att den kan ha de nödvändiga justeringarna av
formatet inbyggt.
Multiplikationer är alltid besvärliga när man vill ha tillbaka
resultatet i samma format. Vad gör man med overflow ?
Båda dina exempel drabbas enkelt av det med bara marginellt
för stora värden på fix1 och fix2.
Korkens kod kom just in. Och den har så klart samma begränsningar
i värderna på de ingående variablerma. Ganska naturligt. För övrigt
så fungerar det.
Re: Fixed point-problem
Multiplicerar du en 16-bitars int med en 16-bitars int och ska stoppa in det i en 16-bitars int så är det bara att ta de 16 lägsta bitarna av resultatet och om nån av de avskurna bitarna är 1 så har du overflow.sodjan skrev:Ingen, enda skillnaden på en "vanlig" int och en "fixed point" är placeringen av
decimalkommat. Även en heltals int är en "fixed point" med kommat på slutet...
Multiplicerar du en 4.12 fixed med en 4.12 fixed och ska stoppa in det i en 4.12 fixed så kan du INTE bara ta de 16 lägsta bitarna. Du måste skifta resultatet först.
Re: Fixed point-problem
Samma sak som man gör om man har ett program som bara använder int och multiplicerar såna?sodjan skrev:Vad gör man med overflow ?
Grejen här är ju att man återanvänder värdena. Produkten från en multiplikation kommer att användas som faktor i nästa varv av loopen. Då kan man ju inte utöka antalet bitar för varje varv...
Det gäller ju att tänka till vid designen, overflow i digital signalbehandling är samma som som att överstyra en analog förstärkare.
Re: Fixed point-problem
Exakt, Nerre !
Det är ingen skillnad. En overflow är alltid en overflow.
Det är ingen skillnad. En overflow är alltid en overflow.
Re: Fixed point-problem
Precis.
Så "problemet" med fixed är helt enkelt att om man bara har en typ av fixed så måste operationerna skifta resultatet.
Vi kan ju göra ett enkelt räkneexempel med tre-bitars tal.
Vi börjar med
010 x 010 som blir 100, inget konstigt alls, som att multiplicera två stycken tre-bitars int.
Men nu gör vi om talen till 1.2 fixed istället.
0.10 x 0.10 blir inte 1.00, det blir 0.01 (eller decimalt, 0,5 x 0,5 = 0,25).
Hade vi stoppat resultatet i en 2.4 fixed så hade det varit 00.0100, vilket bitmässigt stämmer med om vi hade stoppat resultatet av 010 x 010 i en sex-bitars int.
Så "problemet" med fixed är helt enkelt att om man bara har en typ av fixed så måste operationerna skifta resultatet.
Vi kan ju göra ett enkelt räkneexempel med tre-bitars tal.
Vi börjar med
010 x 010 som blir 100, inget konstigt alls, som att multiplicera två stycken tre-bitars int.
Men nu gör vi om talen till 1.2 fixed istället.
0.10 x 0.10 blir inte 1.00, det blir 0.01 (eller decimalt, 0,5 x 0,5 = 0,25).
Hade vi stoppat resultatet i en 2.4 fixed så hade det varit 00.0100, vilket bitmässigt stämmer med om vi hade stoppat resultatet av 010 x 010 i en sex-bitars int.
Re: Fixed point-problem
Exakt igen... 
Det är inte multiplikationen som skiljer utan
den efterföljande tolkningen av resultatet.

Det är inte multiplikationen som skiljer utan
den efterföljande tolkningen av resultatet.
Re: Fixed point-problem
Jo, multiplikationen skiljer.
010 x 010 = 001 (med fixed 1.2)
men
010 x 010 = 100 (med 3-bitars int)
Grundfrågan här är ju vad man menar med fixed point.
Om vi som i mitt exempel har fixed point 1.2 i 3-bitars ord så är det i mina ögon fel att i ett 6-bitars ord stoppa in 2.4. För 6-bitars ord borde det väl blir 4.2 som är mest korrekt? D.v.s. man utökar heltalsdelen, men låter det fortfarande vara 2 decimaler (=fixed).
2.4 är ju inte "fixed" på nåt sätt alls jämfört med 1.2, decimalkommat ligger ju inte samma plats varken från höger eller vänster. Möjligen skulle jag kunna sträcka mig till att 1.5 kan ses som fixed (i relation till 1.2) på samma sätt som 4.2.
010 x 010 = 001 (med fixed 1.2)
men
010 x 010 = 100 (med 3-bitars int)
Grundfrågan här är ju vad man menar med fixed point.
Om vi som i mitt exempel har fixed point 1.2 i 3-bitars ord så är det i mina ögon fel att i ett 6-bitars ord stoppa in 2.4. För 6-bitars ord borde det väl blir 4.2 som är mest korrekt? D.v.s. man utökar heltalsdelen, men låter det fortfarande vara 2 decimaler (=fixed).
2.4 är ju inte "fixed" på nåt sätt alls jämfört med 1.2, decimalkommat ligger ju inte samma plats varken från höger eller vänster. Möjligen skulle jag kunna sträcka mig till att 1.5 kan ses som fixed (i relation till 1.2) på samma sätt som 4.2.
Senast redigerad av Nerre 9 maj 2011, 11:59:07, redigerad totalt 1 gång.
Re: Fixed point-problem
Jag har använt fixtal i min programmering utan att tänka på att det heter så.
Fast då har jag använt dessa ganska blandat med heltal som det passar för tillfället.
ett vanligt exempel:
en förstärkare på analoga ingången har en ungefärlig förstärkning, så man måste justera det inlästa värdet med en konstant man får fram genom kalibrering mot känt värde.
jag lägger på en känd nivå på analoga ingången, som efter AD-omvandling ska motsvara heltalet 10000.
jag läser av ingången och får t.ex. resultatet 10550.
Då beräknar jag en korrigeringskonstant:
K = Önskat värde / verkligt värde = 10000 / 10550 = 0.94787
K är ett fixtal med typiska konfigurationen 1.15. Men det är definierat som ett vanligt heltal och får värdet 10000*32768/10550 = 31060.
När jag sedan ska korrigera ett inläst värde räknar jag bara åt andra hållet:
Värde = indata * K
Även detta måste givetvis shiftas rätt:
exempel: värde = 8440 * K = 8440 * 31060 / 32768 = 8000
Här skulle det ju bli "overflow" i varje operation om jag inte använde 32-bitars resultat från multiplikationerna som jag sedan skalar ner igen till 16-bitars.
Hade jag gjort K till ett 0.16 fixtal istället hade jag fått dubbel noggrannhet. Å andra sidan skull det då aldrig gå att korrigera uppåt , då Kmax blir 0.1111111111111111
Fast då har jag använt dessa ganska blandat med heltal som det passar för tillfället.
ett vanligt exempel:
en förstärkare på analoga ingången har en ungefärlig förstärkning, så man måste justera det inlästa värdet med en konstant man får fram genom kalibrering mot känt värde.
jag lägger på en känd nivå på analoga ingången, som efter AD-omvandling ska motsvara heltalet 10000.
jag läser av ingången och får t.ex. resultatet 10550.
Då beräknar jag en korrigeringskonstant:
K = Önskat värde / verkligt värde = 10000 / 10550 = 0.94787
K är ett fixtal med typiska konfigurationen 1.15. Men det är definierat som ett vanligt heltal och får värdet 10000*32768/10550 = 31060.
När jag sedan ska korrigera ett inläst värde räknar jag bara åt andra hållet:
Värde = indata * K
Även detta måste givetvis shiftas rätt:
exempel: värde = 8440 * K = 8440 * 31060 / 32768 = 8000
Här skulle det ju bli "overflow" i varje operation om jag inte använde 32-bitars resultat från multiplikationerna som jag sedan skalar ner igen till 16-bitars.
Hade jag gjort K till ett 0.16 fixtal istället hade jag fått dubbel noggrannhet. Å andra sidan skull det då aldrig gå att korrigera uppåt , då Kmax blir 0.1111111111111111
Re: Fixed point-problem
> har fixed point 1.2 i 3-bitars ord så är det i mina ögon fel att i ett 6-bitars ord stoppa in 2.4.
> För 6-bitars ord borde det väl blir 4.2 som är mest korrekt?
Nja, det måste vara 2.4 för att inte tappa något i decimalerna.
Sedan för man göra om detta till valfritt format med t.ex trunkering
eller avrundning av decimalerna. Visst, om man trunkerar så behöver man
kanke inte de extra decimarerna alls , och om man gör en förenklad avrundning
så kanske det räcker med en extra "decimal-bit".
Det är lite samma sak som att 0.25 x 0.25 = 0.0625.
Notera dubbla antalet decimala "siffror". Sen att det kan
avrundas till 0.06 är en lite annan fråga och har inte direkt med
multiplikationen som sådan att göra.
Och på samma sätt behövs det aldrig mer en det dubbla antalat heltals-bitar.
Max är : 1.11 x 1.11 = 11.0001 (binärt). Det kan aldrig bli 100.xx (d.v.s 4 decimalt).
> Jo, multiplikationen skiljer.
>
> 010 x 010 = 001 (med fixed 1.2)
> men
> 010 x 010 = 100 (med 3-bitars int)
Njae, igentligen inte...
Du har två "decimal-bitar" i varje faktor och resultatet får då fyra decimalbitar.
D.v.s "tolkningen" av resultatet måste ske korrekt, multiplikationen sker
dock på samma sätt som vanligt. Alltså :
> 0.10 x 0.10 = 00.0100 (format: 1.2 x 1.2 = 2.4)
> 010 x 010 = 000100 (format : 3.0 x 3.0 = 6.0)
Notera att det är samma binära siffror och samma multiplikation i båda fallen
och *multiplikationen* kan göras helt utan hänsyn till att det är fixed point.
Sen får man stuva om detta efter tycke och smak. Man kan t.ex välja att
plocka ut just 1.2 igen ("0.01"), men risk för overflow, så klart...
> För 6-bitars ord borde det väl blir 4.2 som är mest korrekt?
Nja, det måste vara 2.4 för att inte tappa något i decimalerna.
Sedan för man göra om detta till valfritt format med t.ex trunkering
eller avrundning av decimalerna. Visst, om man trunkerar så behöver man
kanke inte de extra decimarerna alls , och om man gör en förenklad avrundning
så kanske det räcker med en extra "decimal-bit".
Det är lite samma sak som att 0.25 x 0.25 = 0.0625.
Notera dubbla antalet decimala "siffror". Sen att det kan
avrundas till 0.06 är en lite annan fråga och har inte direkt med
multiplikationen som sådan att göra.
Och på samma sätt behövs det aldrig mer en det dubbla antalat heltals-bitar.
Max är : 1.11 x 1.11 = 11.0001 (binärt). Det kan aldrig bli 100.xx (d.v.s 4 decimalt).
> Jo, multiplikationen skiljer.
>
> 010 x 010 = 001 (med fixed 1.2)
> men
> 010 x 010 = 100 (med 3-bitars int)
Njae, igentligen inte...

Du har två "decimal-bitar" i varje faktor och resultatet får då fyra decimalbitar.
D.v.s "tolkningen" av resultatet måste ske korrekt, multiplikationen sker
dock på samma sätt som vanligt. Alltså :
> 0.10 x 0.10 = 00.0100 (format: 1.2 x 1.2 = 2.4)
> 010 x 010 = 000100 (format : 3.0 x 3.0 = 6.0)
Notera att det är samma binära siffror och samma multiplikation i båda fallen
och *multiplikationen* kan göras helt utan hänsyn till att det är fixed point.
Sen får man stuva om detta efter tycke och smak. Man kan t.ex välja att
plocka ut just 1.2 igen ("0.01"), men risk för overflow, så klart...
