Add initial fixed point number implementation
This commit is contained in:
parent
f872bcc0c9
commit
34495b580b
@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
project(mtl LANGUAGES CXX C ASM)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
set(TARGET_SRC_FILES src/memcpy.s src/string.cpp)
|
||||
set(TARGET_SRC_FILES src/memcpy.s src/string.cpp src/fixed.s)
|
||||
set(TARGET_PUB_INCLUDE_FILES include/mtl/utility.hpp include/mtl/string.hpp include/mtl/fsm.hpp)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${TARGET_SRC_FILES} ${TARGET_PUB_INCLUDE_FILES})
|
||||
|
||||
83
include/mtl/fixed.hpp
Normal file
83
include/mtl/fixed.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* \brief Fixed point multiply assembly implementation
|
||||
*
|
||||
* DO NOT USE DIRECTLY! Use fixed::operator* instead
|
||||
*/
|
||||
extern "C" int32_t fixed_mul(int32_t x, int32_t y);
|
||||
|
||||
namespace mtl {
|
||||
/**
|
||||
* \brief 32-bit Fixed point number
|
||||
*
|
||||
* Uses a base of 64. ie. the lower 6 bits are after the decimal place,
|
||||
* the other 26 bits are before the decimal place.
|
||||
*
|
||||
* Valid values are in the range ~[-33'554'431.01, 33'554'432.98]
|
||||
*
|
||||
* Has a maximum error of +/- 1/128 (~0.0078), integers are always
|
||||
* exactly.
|
||||
*/
|
||||
class fixed {
|
||||
int32_t x;
|
||||
|
||||
/**
|
||||
* \brief Raw constructor
|
||||
*
|
||||
* Creates a new fixed point number with the raw data of x.
|
||||
* DO NOT use to set the fixed number to an integer value, use
|
||||
* the public constructor instead.
|
||||
*/
|
||||
constexpr fixed(int32_t _x, bool) : x(_x) {}
|
||||
|
||||
public:
|
||||
constexpr fixed() : x(0) {}
|
||||
/**
|
||||
* \brief 32-bit integer constructor
|
||||
*
|
||||
* Creates a new fixed point number with the value of the integer.
|
||||
* Must be within the range represented by fixed point numbers, see
|
||||
* the class description for more detail.
|
||||
*/
|
||||
constexpr fixed(int32_t _i) : x(_i * 64) {}
|
||||
/**
|
||||
* \brief Floating point constructor
|
||||
*
|
||||
* Creates a new fixed point number with the closest number to
|
||||
* the floating point number. Must be within the range represented by
|
||||
* fixed point numbers, see the class description for more detail.
|
||||
*/
|
||||
constexpr fixed(float _f)
|
||||
// 0.5 offset accounts for truncating to integer, round instead
|
||||
: x((_f * 64) + 0.5f) {}
|
||||
|
||||
/**
|
||||
* \brief Fixed point addition
|
||||
*
|
||||
* Addition with fixed point numbers is the same as with a 32-bit
|
||||
* integer, so should be extremely quick.
|
||||
*/
|
||||
fixed operator+(fixed rhs) const {
|
||||
return fixed(x + rhs.x, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fixed point multiplication
|
||||
*
|
||||
* Uses an assembly implementation to multiply the two numbers.
|
||||
* Not as quick as an integer multiplication. Use sparringly.
|
||||
*
|
||||
* Tested on the MGBA Gameboy Advance emulator, takes around 90
|
||||
* cycles when the assembly routine is placed in IWRAM.
|
||||
* The Gameboy Advance uses an armv7tdmi, and IWRAM is the fastest
|
||||
* available RAM.
|
||||
*/
|
||||
fixed operator*(fixed rhs) const {
|
||||
return fixed(fixed_mul(x, rhs.x), true);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mtl
|
||||
11
src/fixed.s
Normal file
11
src/fixed.s
Normal file
@ -0,0 +1,11 @@
|
||||
.section .iwram, "ax", %progbits
|
||||
.arm
|
||||
.align 2
|
||||
|
||||
.global mtl_fixed_mul
|
||||
.type mtl_fixed_mul STT_FUNC
|
||||
mtl_fixed_mul:
|
||||
smull r2, r3, r0, r1
|
||||
lsr r0, r2, #6
|
||||
orr r0, r3, lsl #26
|
||||
bx lr
|
||||
Loading…
x
Reference in New Issue
Block a user