Solving quadratics using the quadratic equation
The quadratic equation is given as:
How to do it.
| Register | Purpose |
|---|---|
| d0 | a coefficient |
| d1 | b coefficient |
| d2 | c coefficient |
| d3 | -b |
| d4 | b2 & root 1 |
| d5 | 4ac & root 2 |
| d6 | 2a |
| d7 | b2-4ac |
| d8 | x(n) |
| d9 | x(n+1) |
The process requires calculating a square root. This will be done using the same method for calculating cube roots shown on the cube roots page. That is, the Newton-Raphson method.
The derivation of the square root formula is the same process as for the cube root. Only the outcome is different so I'll skip to the end and say that the estimate of the square root is given by:
Unlike the cube root calculation, this one is very straight forward. The pseudocode looks like:
- Start with estimate of root, x(n).
- Calculate N / x(n)
- Add x(n)
- Divide by 2
- Compare result with x(n)
- If the values have converged then break
- Otherwise, repeat.
It is accomplished with this code:
root_loop:
fdiv d9, d7, d8 // d9 = N/x(i)
fadd d9, d9, d8 // d9 = x(i) + N/x(i)
fmov d10, #2
fdiv d9, d9, d10 //d9 = 1/2(x(i) + N/x(i))
fcmp d8, d9
B.EQ final_calc
fmov d8, d9
b root_loop
The registers being used here are:
| Register | Purpose |
|---|---|
| d7 | N [=sqrt(b2-4ac)] |
| d8 | Estimate of x(n) |
| d9 | x(n+1) |
| d10 | 2. Used to perform /2 |
Source Code
// quadratic1.s
// An app to solve quadratic equations of the form ax^2 + bx +c
// where a, b, c are integers
.global main
.extern scanf
.extern printf
.data
a_input_msg:
.asciz "Value for a: "
b_input_msg:
.asciz "Value for b: "
c_input_msg:
.asciz "Value for c: "
a_fmt:
.asciz "%lf"
b_fmt:
.asciz "%lf"
c_fmt:
.asciz "%lf"
a:
.double 0
b:
.double 0
c:
.double 0
output_message:
.asciz "%lfx^2 + %lfx + %lf = (x + %lf)(x + %lf)\n"
no_roots_output:
.asciz "No real roots.\n"
test_output:
.asciz "a = %lf, b = %lf, c = %lf\n"
.text
main:
// prolog
stp x29, x30, [sp, -16]!
mov x29, sp
// main code
ldr x0, =a_input_msg
bl printf
ldr x0, =a_fmt
ldr x1, =a
bl scanf
ldr x0, =b_input_msg
bl printf
ldr x0, =b_fmt
ldr x1, =b
bl scanf
ldr x0, =c_input_msg
bl printf
ldr x0, =c_fmt
ldr x1, =c
bl scanf
test:
ldr x0, =test_output
ldr x1, =a
ldr d0, [x1] // a in d0
ldr x2, =b
ldr d1, [x2] // b in d1
ldr x3, =c
ldr d2, [x3] // c in d2
// bl printf
fneg d3, d1 // -b in d3
fmul d4, d1, d1 // b^2 in d4
fmul d5, d0, d2 // a*c in d5
fmov d6, #4
fmul d5, d5, d6 // 4ac in d5
fadd d6, d0, d0 // 2a in d6
fcmp d4, d5
B.LT no_roots
fsub d7, d4, d5 // b^2 - 4ac in d7
fmov d8, #4
fdiv d8, d7, d8 // new estimate for x(n)
root_loop:
fdiv d9, d7, d8 // d9 = N/x(i)
fadd d9, d9, d8 // d9 = x(i) + N/x(i)
fmov d10, #2
fdiv d9, d9, d10 //d9 = 1/2(x(i) + N/x(i))
fcmp d8, d9
B.EQ final_calc
fmov d8, d9
b root_loop
final_calc:
fadd d4, d3, d8 // -b + sqrt
fdiv d4, d4, d6 // /2a. d4 now has first root
fsub d3, d3, d8 // -b - sqrt
fdiv d3, d3, d6 // /2a. d3 now has second root
ldr x0, =output_message
bl printf
b end
no_roots:
ldr x0, =no_roots_output
bl printf
end:
// clean up
mov x0, #0
ldp x29, x30, [sp], 16
RET