Task

Implement the algorithm to compute the principal   nth   root   





A

n





{\displaystyle {\sqrt[{n}]{A}}}

   of a positive real number   A,   as explained at the   Wikipedia page.



 
/* ARM assembly Raspberry PI  */
/*  program nroot.s   */
/* compile with option -mfpu=vfpv3 -mfloat-abi=hard */ 
/* link with gcc. Use C function for display float */  
 
/* Constantes               */
.equ EXIT,   1                         @ Linux syscall
 
/* Initialized data */
.data
szFormat1:         .asciz " %+09.15f\n"
.align 4
iNumberA:          .int 1024
 
/* UnInitialized data */
.bss 
.align 4
 
/*  code section */
.text
.global main 
main:                                   @ entry of program
    push {fp,lr}                        @ saves registers
 
    /* root 10ieme de 1024  */
    ldr r0,iAdriNumberA                 @ number address
    ldr r0,[r0]
    vmov s0,r0                          @ 
    vcvt.f64.s32 d0, s0                 @conversion in float single précision (32 bits)
    mov r0,#10                          @ N
    bl nthRoot
    ldr r0,iAdrszFormat1                @ format
    vmov r2,r3,d0
    bl printf                           @ call C function !!!
                                        @ Attention register dn lost !!!
    /* square root of 2   */ 
    vmov.f64 d1,#2.0                    @ conversion 2 in float register d1
    mov r0,#2                           @ N
    bl nthRoot
    ldr r0,iAdrszFormat1                @ format
    vmov r2,r3,d0
    bl printf                           @ call C function !!!
 
100:                                    @ standard end of the program
    mov r0, #0                          @ return code
    pop {fp,lr}                         @restaur  registers
    mov r7, #EXIT                       @ request to exit program
    swi 0                               @ perform the system call
 
iAdrszFormat1:           .int szFormat1
iAdriNumberA:            .int iNumberA
 
/******************************************************************/
/*     compute  nth root                                          */ 
/******************************************************************/
/* r0 contains N   */
/* d0 contains the value                 */
/* d0 return result                      */
nthRoot:
    push {r1,r2,lr}                    @ save  registers 
    vpush {d1-d8}                         @ save float registers
    FMRX    r1,FPSCR                   @ copy FPSCR into r1
    BIC     r1,r1,#0x00370000          @ clears STRIDE and LEN
    FMXR    FPSCR,r1                   @ copy r1 back into FPSCR
 
    vmov s2,r0                         @ 
    vcvt.f64.s32 d6, s2                @ N conversion in float double précision (64 bits)
    sub r1,r0,#1                       @ N - 1
    vmov s8,r1                         @ 
    vcvt.f64.s32 d4, s8                @conversion in float double précision (64 bits)
    vmov.f64 d2,d0                     @ a = A
    vdiv.F64 d3,d0,d6                  @ b = A/n
    adr r2,dfPrec                      @ load précision
    vldr d8,[r2]                  
1:                                     @ begin loop
    vmov.f64 d2,d3                     @ a <- b
    vmul.f64 d5,d3,d4                  @ (N-1)*b
 
    vmov.f64 d1,#1.0                   @ constante 1 -> float
    mov r2,#0                          @ loop indice
2:                                     @ compute pow (n-1)
    vmul.f64 d1,d1,d3                  @ 
    add r2,#1
    cmp r2,r1                          @ n -1 ?
    blt 2b                             @ no -> loop
    vdiv.f64 d7,d0,d1                  @ A / b pow (n-1)
    vadd.f64 d7,d7,d5                  @ + (N-1)*b
    vdiv.f64 d3,d7,d6                  @ / N -> new b
    vsub.f64 d1,d3,d2                  @ compute gap
    vabs.f64 d1,d1                     @ absolute value
    vcmp.f64 d1,d8                     @ compare float maj FPSCR
    fmstat                             @ transfert FPSCR -> APSR
                                       @ or use VMRS APSR_nzcv, FPSCR
    bgt 1b                             @ if gap > précision -> loop 
    vmov.f64 d0,d3                     @ end return result in d0
 
100:
    vpop {d1-d8}                       @ restaur float registers
    pop {r1,r2,lr}                     @ restaur arm registers
    bx lr
dfPrec:            .double 0f1E-10     @ précision
 
 