| Volver menú revistas | Número 1 - JULIO 1992 |
Página anterior |
| SOURCES Y SOURCESITOS
Nos gustaría en cada número, incluir algunas rutinas, bien en ensamblador o en cualquier otro lenguaje, pues creemos que pueden ser interesantes. Así que ya sabéis, si tenéis alguna, ¡enviarla ya!. En este primer número incluimos una rutina bastante interesante para extraer raíces cuadradas, tanto en Assembler como en C. ; Esta es una rutina super-rápida para extraer la raiz cuadrada de
; un número
; (En principio de 16 bits)
;
; © OTTO PETER, Innsbruck
ROOT:
; SETTINGS IN: D0.w - number
;
; OUT: D0.w - result
; - sign- and zeroflag are valid
movem.w d1-d3,-(sp)
move.w #$4000,d2
root_loop:
move.w d1,d3
add.w d2,d3
lsr.w #1,d1
cmp.w d3,d0
ble.s boing
sub.w d3,d0
or.w d2,d1
boing:
lsr.w #2,d2
bne.s root_loop
cmp.w d1,d0
blt.s no_round_up
addq.w #1,d1
no_round_up:
move.w d1,d0
movem.w (sp)+,d1-d3
rts
;*************************************************
; Rutina para números en 32 bits
;*************************************************
exp_offset: equ $7f
domain_error: ;Error if number is negative
movem.l (a7)+,d1-d4
rts
sq_0:
clr.l d0
movem.l (a7)+,d1-d4
rts
sqrt:
movem.l d1-d4,-(a7) ;Save d1-d4
move.l d0,d4
bmi.s domain_error ;Error if number is negative
swap d4 ;MSW of number
and.l #$7f80,d0 ;isolate exponent
beq.s sq_0 ;exponent is 0 => root is 0
and.l #$007fffff,d0 ;isolate mantisse
sub.w #exp_offset*$80,d4 ;exponent in `2^i`-format
bclr #7,d4 ;exponent even?
beq.s even_exp
add.l d0,d0 ;mantisse * 2
add.l #$01000000-$00800000,d0 ;set hidden-bit
even_exp:
asr.w #1,d4 ;exponent / 2
add.w #exp_offset*$80,d4 ;exponent in offset-format
swap d4
lsl.l #7,d0
move.l #$40000000,d2 ;xroot after 1. interation
move.l #$10000000,d3 ;m2 = 2 << (maxbit-1)
loop1_0:
move.l d0,d1 ;xx2 = x
loop1_1:
sub.l d2,d1 ;xx2 -= xroot
lsr.l #1,d2 ;xroot >>= 1
sub.l d3,d1 ;x2 -= m2
bmi.s dont_set1
move.l d1,d0 ;x = xx2
or.l d3,d2 ;xroot += m2
lsr.l #2,d3 ;m2 >>= 2
bne.s loop1_1
bra.s d0_d1_same
dont_set1:
lsr.l d2,d3 ;m2 >>= 2
bne.s loop1_0 ;repeat loop 15 times (bit 22..8)
move.l d0,d1
d0_d1_same:
sub.l d2,d1 ;xx2 -= xroot
ror.l #1,d2 ;xroot >>= 1 (with carry)
swap d2 ;turn to new aligment
subq.l #1,d1 ;carry of 0-0x4000: x2 -= m2 (part 1)
bmi.s dont_set7
or.l #-$40000000,d1 ;0-0x4000: x2 -= m2 (part 2)
move.l d1,d0
or.w #$4000,d2
dont_set7:
swap d0 ;turn x to new aligment
move.w #$1000,d3 ;m2 - bit 16..31 = 0
loop2_0:
move.l d0,d1 ;xx2 = x
loop2_1:
sub.l d2,d1 ;xx2 = xroot
lsr.l #1,d2 ;xroot >>= 1
sub.l d3,d1
bmi.s dont_set2
move.l d1,d0 ;x = xx2
or.l d3,d2 ;xroot += m2
lsr.w #2,d3 ;m2 >>= 2
bne.s loop2_1
bra.s finish
dont_set2:
lsr.w #2,d3 ;m2 >>= 2
bne.s loop2_0 ;repeat loop 7 times (n=6..0)
finish:
sub.l d2,d0 ;round root?
bls.s no_inc
addq.l #1,d2 ;round up!
no_inc:
bclr #23,d2 ;clear hidden bit
or.l d4,d2 ;combine exponent and mantisse
move.l d2,d0 ;result
movem.l (a7)+,d1-d4
rts
---------------- C -------------------------------
#define N_BITS 32
#define MAX_BIT ((N_BITS + 1) / 2 - 1)
unsigned long int sqrt_1(x)
unsigned long int x;
{
register int i;
register unsigned long int m, r, root;
root = 0; m = 1 << MAX_BIT
for (i = MAX_BIT; i >= 0; i--)
{
r = root + m;
if (r * r <= X) root = r;
m >>= 1;
}
return root;
}
unsigned long int sqrt_2(x)
unsigned long int x;
{
register long int i;
register unsigned long int m, r2, root;
unsigned long int root2;
root2 = root = 0; m = 1 << MAX_BIT;
for (i = MAX_BIT; i >= 0; i--)
{
r2 = root2 + (root << i + 1) + (1 << i + i);
if (r2 <= X)
{
root2 = r2; root += m;
}
m >>= 1;
}
return root;
}
unsigned long int sqrt_3(x)
unsigned long int x;
{
register unsigned long int m2, r2, xroot, root2;
int i;
root2 = xroot = 0; m2 = 1 << MAX_BIT * 2;
for (i = MAX_BIT; i >= 0; i--)
{
r2 = root2 + xroot + m2;
xroot >>= 1;
if (r2 <= X)
{
root2 = r2; xroot += m2;
}
m2 >>= 2;
}
return xroot;
}
unsigned long int sqrt_4(x)
unsigned long int x;
{
register unsigned long int xroot, m2, x2;
xroot = 0; m2 = 1 << MAX_BIT * 2;
do
{
x2 = xroot + m2;
xroot >>= 1;
if (x2 <= X)
{
x -= x2; xroot += m2;
}
}
while (m2 >>= 2);
return xroot;
}
unsigned long int sqrt_5(x)
unsigned long int x;
{
register unsigned long int xroot, m2, x2;
xroot = 0; m2 = 1 << MAX_BIT * 2;
do
{
x2 = xroot + m2;
xroot >>= 1;
if (x2 <= X)
{
x -= x2; xroot += m2;
}
}
while (m2 >>= 2);
if (xroot < x) return xroot + 1;
return xroot;
}
|