Search code examples
recursionmips

Floating point accuracy in recursive exponentiation MIPS


I am trying to write MIPS code that computes number's power recursively. Everything seems to be correct, but in one test case I got 5^-2 = 0.04000000000000001. I assume that it is due to my computer's architecture. Am I right or is there something wrong in my code?

For better understanding there is an array of doubles and an array of integer powers in data segment.

Here's code:

.data
double_array: .double 5.0 2.0 -3.0 -3.0 -4.2 5.0 -2.0 0.0 0.0
power_array: .word -2 -4 2 1 0 -2 -3 0 10
N_OF_CASES: .word 9
str_case: .asciiz "case_"
str_colon: .asciiz ": "
str_equal: .asciiz " = "
str_power: .asciiz "^"
str_newLine: .asciiz "\n"
one: .double 1.0
zero: .double 0.0

main:
    lw $t1, N_OF_CASES
    la $t2, double_array
    la $t3, power_array
    li $t4, 0

loop:
    lw $a1, ($t3)
    lw $t0, ($t3)
    l.d $f14, ($t2)
    l.d $f16, ($t2)
    jal power
    
    li $v0, 3
    mov.d $f12, $f16
    syscall
    
    li $v0, 4
        la $a0, str_power
        syscall
        
        li $v0, 1
        move $a0, $t0
        syscall
        
        li $v0, 4
        la $a0, str_equal
        syscall
        
        li $v0, 3
        mov.d $f12, $f0
        syscall
        
        la $v0, 4
        la $a0, str_newLine
        syscall
    
    addi $t2, $t2, 8
    addi $t3, $t3, 4
    addi $t4, $t4, 1
    subi $t1, $t1, 1
    
    bnez $t1, loop
    
    li $v0 10
    syscall
power:
    andi $sp 0xfffffff8
    addi $sp $sp -16
    s.d $f20 ($sp)
    sw $ra 8($sp)
    
    li $t7, 0
    beq $a1, $t7, base_case
    
    bgez $a1, not_negative
    
    l.d $f2, one
    div.d $f14, $f2, $f14
    li $t6, -1
    mul $a1, $a1, $t6
    j power

not_negative:
    mov.d $f2, $f14
    subi $a1, $a1, 1
    jal power
    mul.d $f0, $f0, $f2

power_done:
    l.d $f20, ($sp)
    lw $ra, 8($sp)
    addi $sp, $sp, 16
    
    jr $ra
    
base_case:
    l.d, $f0, one
    j power_done

Solution

  • Your question is answered by the floating point reference I provided in comment.

    However, about the posted code, the j power is highly suspicious.  It jumps to the beginning of the function, runs the prologue and creates another stack frame, though without having been called.  If this is trying to do Tail Call Optimization, you should skip over the prologue to re-enter the function just after prologue.  Otherwise, jal power is more appropriate though you'll have to add j powerDone after.

    Your register usages are non-standard.