Forum: Mikrocontroller und Digitale Elektronik 40 bit Wurzel AVR ASM


von Sebi (Gast)


Lesenswert?

Der Betreff sagt es ja schon. Hat jemand eine fertige Routine?

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Sebi schrieb:
> Der Betreff sagt es ja schon.

Schön wärs. ;-)

Für welchen Mikrocontroller genau?

Was meinst du mit 40 Bit? Ist das die Genauigkeit der Zahl?

In welchem Format hast du den Radikand und in welchem Format brauchst du 
das Ergebnis?

von Sebi (Gast)


Lesenswert?

Hallo Markus,
entschuldige, dass ich die Informationen vergessen habe.
Also:
-ATMEGA88PA
Format Radikand: 40bit Integer
Format Ergebniss: 20bit Integer, gerundet (ob auf oder ab ist ja egal)y

Ich hab mir schon die 32bit Wurzel Funktion hier im Wiki angeschaut. 
Allerdings weiß ich nicht, wie ich die "erweitern" kann.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sebi schrieb:

> Ich hab mir schon die 32bit Wurzel Funktion hier im Wiki angeschaut.
> Allerdings weiß ich nicht, wie ich die "erweitern" kann.

Anstatt 4-Byte Eingabe wird's eine 5-Byte Eingabe.
Anstatt 2-Byte Ausgabe wird's eine 3-Byte Ausgabe.

In einem ersten Schritt kannst du die hartcodierten Register zum 
bwesseren Überblick ersezten:
 
1
ldi   R19, 0xc0
2
clr   R18          ; rotation mask in R19:R18
3
ldi   R27, 0x40
4
sub   R26, R26     ; developing sqrt in R27:R26, C=0

wird dann zu
 
1
#define RES 26
2
#define MASK 18
3
#define BITS 40
4
5
; rotation mask in MASK
6
ldi   MASK+1, 3 << ((BITS-2) % 8)
7
clr   MASK
8
9
; expand sqrt in RES, C=0
10
ldi   RES+1, 1 << ((BITS/2-2) % 8)
11
sub   RES,   RES
12
13
...
14
15
#undef BITS
16
#undef MASK
17
#undef RES

In einem 2. Schritt erweiterst du dann die Arbeitsregister zur jeweils 
benötigten Bitbreite:
1
; rotation mask in MASK
2
ldi   MASK+2, 3 << ((BITS-2) % 8)
3
clr   MASK+1
4
clr   MASK

Die Shifts oben musst noch nachrechnen (Hausaufgabe).

hmmm. oder erweitern auf 6 Byte Radikant, die Routine setzt wohl voraus, 
daß der Radikant eine gerade Anzahl Bytes groß ist, d.h. das Erhebnis 
nicht 2.5 Bytes groß ist.

von Sebi (Gast)


Lesenswert?

Ich werde mich mal an der 48bit Variante versuchen und die dann hier 
posten.

von Wolfgang (Gast)


Lesenswert?

Zur Erweiterung auf 40 bit sollte auch die Näherung
1
 sqrt(1+x) = 1 + x/2 + eps
gut sein.

von Sebi (Gast)


Lesenswert?

Verlfucht, ich krieg es nicht hin.
Andere Baustelle: Heron Verfahren.
Wie krieg ich das ohne die Division Xn/a hin? Division durch zwei ist ja 
kein Ding (shift) aber die andere Division bereit mir Kopfzerbrechen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wolfgang schrieb:
> Zur Erweiterung auf 40 bit sollte auch die Näherung
>
1
 sqrt(1+x) = 1 + x/2 + eps
> gut sein.

Aber nur für |x| << 1

von Sebi (Gast)


Lesenswert?

1
;  R18:R17:R16=SQRT(R6:R5:R4:R3:R2:R1)
2
SQRT48:
3
    ldi r21,0xc0 
4
    clr r20
5
    clr r19
6
    ldi   R18,0x40
7
        clr r17
8
    sub r16,r16
9
_sq48_1:    brcs  _sq48_2
10
    cp r4,r16
11
    cpc r5,r17
12
    cpc r6,r28
13
    brcs  _sq48_3
14
_sq48_2:    sub   R4,R16
15
    sbc r5,r17
16
    sbc r6,r18
17
    or r16,r19
18
    or r17,r20
19
    or r18,r21
20
_sq48_3:    lsr   R21
21
    ror r20
22
    ror r19
23
    eor r18,r21
24
    eor r17,r20
25
    eor r16,r19
26
    rol r1
27
    rol r2
28
    rol r3
29
    rol r4
30
    rol r5
31
    rol r6
32
    sbrs r1,0
33
    rjmp  _sq48_1 
34
35
    brcs  _sq48_4
36
    lsl   R3
37
    cpc   R16,R4
38
    cpc   r17,r5
39
    cpc    r18,r6
40
_sq48_4:    adc   R16,r21
41
ret

das ist der klägliche Versuch.

von Horst H. (horha)


Lesenswert?

Hallo,

als ich
 sqrt(1+x) = 1 + x/2 + eps  heute gesehen habe, fiel mir spotan soetwas 
ein:
Falls die Zahl kleiner 32 -Bit ist einfach 32 Bit Rechnung.-> trivial.
Falls die Zahl >=2^32 ist dann die Zahl aufspalten
N = K*256 + C mit K = oberen 32 Bits und C = N mod 255 also die unter 8 
Bit

Wurzel(N)=Wurzel(K*256 + C)
erweitert mit 1=Wurzel(K*256)/Wurzel(K*256)
=Wurzel(K*256)*Wurzel( (K*256)/(K*256) + C/(K*256))

= Wurzel(K*256)*Wurzel( 1+ C/(K*256))
x = c/(256*K) | irgenwas kleiner 2^-24 < 1e-7
= 16*Wurzel(K) + (16*Wurzel(K)* C/(256*K)/2
= 16*Wurzel(K) // + C/(16*Wurzel(K))/2 < 1/512 )
Dummerweise ist Wurzel(K) nur eine 16 Bit Integerzahl. :-(
Wenn man eine Wurzelfunktion hätte, die 32 Bit integer ins 16.8 Format 
umrechnen würde, hätte man ein Chance.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.