Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Fixed Point Arithmetic C++14 Library

License

NotificationsYou must be signed in to change notification settings

mizvekov/fp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This is a C++14 header-only fixed-point arithmetic library.

It's purpose is to wrap another type and provide fixed point arithmeticsupport on top of it.

It's designed to be able to wrap on top of all the built-in arithmetic types(integers and floating point types) as well as user defined arithmetic types.

Examples of other arithmetic types which are tested andpreliminary adapters are provided:

  • boostrational
  • boost multiprecisioncpp_int andcpp_bin_float
  • David Stone'sbounded_integer

The following is a sample of what can be achieved by employing this library:

usingnamespacefp;auto x = make_fp<4,int >(3.25);auto y = make_fp<8,char>(0.75);auto z = x * y;// now z is of type fp_t<int,12>std::cout <<double(z);// prints 2.4375// using David Stone's bounded_integerusingnamespacebounded::literal;usingnamespacefp::constants;// import int_ shorthand for std::integral_constant// create a bounded fixed point integer with range [1, 100]// with initial value 30, then perform a virtual right shift// by 3.auto x =fp_t<bounded::integer<1,100>,0>{  30_bi } >> int_<3>;// now x holds 3.75 and has range [0.125, 12.5]//ditto, range [2, 300], initial value 150, virtual right shift by 4auto y =fp_t<bounded::integer<2,300>,0>{ 150_bi } >> int_<4>;// now y holds 9.375 and has range [0.125, 18.75]auto z = x + y;std::cout <<double(z);// prints 13.125// below it shows that type information of the underlying type is not loststd::cout <<double(std::numeric_limits<decltype(z)>::min());// prints 0.25std::cout <<double(std::numeric_limits<decltype(z)>::max());// prints 31.25

It needs at least clang 3.4 to compile.Unit tests are included, and these can be built using CMake.

Example building and running tests on unix system:

cmake -DCMAKE_CXX_COMPILER=clang++<path to source>makectest

How to use

This is a single-header include only library, building is only required for tests.Just#include <fp/fp.hpp> and everything is inside namespacefp. The maintype isfp::fp_t and there is also afp::make_fp helper which does constructionwith type deduction. The namespacefp::constants contains shorthandsint_ anduint_ which can be used for virtual shifting.

Fixed Point Library Description

It implements a template class typefp_t<T, E> whereT is an underlyingarithmetic type andE is an integer representing the binary point position.From now on these will be referred as the underlying type and the exponent,forT andE respectively.

It supports casting between integral and floating point typesand the whole set of arithmetic, bitwise and relational operators.All operations are constexpr themselves, although they are only usable assuch if the underlying type also implements them as constexpr.

A virtual shift may be performed by using astd::integral_constant as ashift amount with the usual shift operators<< and>>. Convenience aliasesint_ anduint_ are provided under namespacefp::constants

All operations preserve the resulting type of the underlying type's operation.

For example, if you have an instancea with typefp_t<A, EXP_A>, and an instanceb with typefp_t<B, EXP_B>, and you multiply them together, the type of the expressiona * b will befp_t<decltype(A{} * B{}), EXP_A + EXP_B>. In the specific case thatA ischar,B isint andEXP_A andEXP_B are2 and3, the resultingtype will befp_t<int, 5>, sincechar{} * int{} has typeint, according to normalC++ conversion rules.

Similar thing happens with unary operations, the expression+fp_t<A, EXP_A>{}has typefp_t<decltype(+A{}), EXP_A>.

The result of a virtual shift has underlying type unchanged, and just theexponent is modified. The expressionfp_t<A, EXP_A>{} >> int_<SA> hastypefp_t<A, EXP_A + SA>.

All the unary operations preserve the exponent, and in the case ofbinary operations, the exponent of the result depends on the operationbeing performed.

For addition, subtraction, modulus and the bitwise operators, the result hasexponent equal to the greatest of the exponents of the operands, and theoperation is carried out as if the operand with the smallest exponent wascast to that same exponent. For example, the result of the expressionfp_t<int, 4>(1) + fp_t<int, 8>(2) has typefp_t<int, 8>

For multiplication and division, the exponent of the result is equal to thesum and subtraction of the exponents of the operands respectively.This implies the expressionfp_t<int, 4>{} * fp_t<int, 8>{} has typefp_t<int, 12>, and with division instead, the resulting type would befp_t<int, -4>

When using the relational operators betweenfp_t numbers with differentexponents, the operand with the greatest exponent is converted so it has thesame exponent as the other one, and they are then compared.This avoids a more expensive operation, and means that only leastsignificant bits are discarded.

Requirements on the underlying type

At a minimum, the underlying type must be default constructible,copy constructible and support left and right shift by astd::integral_constant. The other operators are optional, and ifthey are not supported, the composed type will not support them.For example, if there is no modulus operator implemented forT,thenfp_t<T> will not support modulus either.

License

ISC

Copyright (c) 2018, Matheus Izvekovmizvekov@gmail.com

All rights reserved.

About

Fixed Point Arithmetic C++14 Library

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp