Last active
August 29, 2015 14:24
-
-
Save rasgo-cc/52773a91a4ac96a62bbb to your computer and use it in GitHub Desktop.
Fixed-point multiplication and division
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://theramblingness.com | |
#include <stdio.h> | |
#include <stdint.h> | |
#define Qn 15 // Q-format | |
// These types should be defined according to CPU bitness | |
#define FXPLONG int64_t | |
#define FXPSHORT int32_t | |
int main() | |
{ | |
// Variables | |
uint32_t scaler = (uint32_t)(1<<Qn); | |
FXPLONG tmp = 0; | |
FXPSHORT op1 = 0, op2 = 0; | |
FXPSHORT res; | |
double res_f; | |
double f_op1 = 0.654321; | |
double f_op2 = 0.123456; | |
double f_mul_res = f_op2*f_op2; | |
double f_div_res = f_op1/f_op2; | |
printf("f_op1: %f\n", f_op1); | |
printf("f_op2: %f\n", f_op2); | |
printf("f_mul_res: %f\n", f_mul_res); | |
printf("f_div_res: %f\n", f_div_res); | |
printf("Qn: %u\n", Qn); | |
printf("scaler: %u\n", scaler); | |
printf(" -- Fixed-point multiplication: (op2)^2\n"); | |
op2 = (FXPSHORT)(f_op2*(double)scaler); | |
op1 = op2; | |
printf("op1: %d\n", op1); | |
printf("op2: %d\n", op2); | |
// Multiplication | |
// (the cast may also be applied to each operand individually) | |
tmp = (FXPLONG)op1*(FXPLONG)op2; | |
// Rounding | |
tmp = tmp + (FXPLONG)(1 << Qn); | |
// Truncation | |
tmp = tmp >> Qn; | |
// Discard the upper-half bytes of tmp to get the final result | |
res = (FXPSHORT) tmp; | |
res_f = (double)res/(double)scaler; | |
printf("res: %d (%f)\n", res, res_f); | |
printf("err: %f\n", res_f - f_mul_res); | |
printf(" -- Fixed-point division: op1/op2\n"); | |
op1 = (FXPSHORT)(f_op1*(double)scaler); | |
op2 = (FXPSHORT)(f_op2*(double)scaler); | |
printf("op1: %08X %d (%f)\n", op1, op1, f_op1); | |
printf("op2: %08X %d (%f)\n", op2, op2, f_op2); | |
// Convert dividend to Q(2*n) format | |
tmp = ((FXPLONG)op1 << Qn); | |
// Round by summing half the divisor | |
tmp += op2 >> 1; | |
// Division | |
tmp /= (FXPLONG)(op2); | |
res = (FXPSHORT) tmp; | |
res_f = (double)res/(double)scaler; | |
printf("res: %08X %d (%f)\n", res, res, res_f); | |
printf("err: %f\n", res_f - f_div_res); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment