You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
FixedPointsArduino/src/FixedPoints/Utils.h

256 lines
9.8 KiB

// Copyright 2017 Pharap
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "Details.h"
#include "UFixed.h"
#include "SFixed.h"
//
// Declaration
//
FIXED_POINTS_BEGIN_NAMESPACE
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> floorFixed(const UFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> floorFixed(const SFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> ceilFixed(const UFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> ceilFixed(const SFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> roundFixed(const UFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> roundFixed(const SFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr bool signbitFixed(const SFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> absFixed(const SFixed<Integer, Fraction> & value);
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> copysignFixed(const SFixed<Integer, Fraction> & x, const SFixed<Integer, Fraction> & y);
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> nextafterFixed(const SFixed<Integer, Fraction> & from, const SFixed<Integer, Fraction> & to);
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> nextafterFixed(const UFixed<Integer, Fraction> & from, const UFixed<Integer, Fraction> & to);
//
// Unsigned Random
//
#if !defined(FIXED_POINTS_NO_RANDOM)
template< unsigned Integer, unsigned Fraction >
UFixed<Integer, Fraction> randomUFixed(void);
template< unsigned Integer, unsigned Fraction >
UFixed<Integer, Fraction> randomUFixed(const UFixed<Integer, Fraction> & exclusiveUpperBound);
template< unsigned Integer, unsigned Fraction >
UFixed<Integer, Fraction> randomUFixed(const UFixed<Integer, Fraction> & inclusiveLowerBound, const UFixed<Integer, Fraction> & exclusiveUpperBound);
#endif
//
// Signed Random
//
#if !defined(FIXED_POINTS_NO_RANDOM)
template< unsigned Integer, unsigned Fraction >
SFixed<Integer, Fraction> randomSFixed(void);
template< unsigned Integer, unsigned Fraction >
SFixed<Integer, Fraction> randomSFixed(const SFixed<Integer, Fraction> & exclusiveUpperBound);
template< unsigned Integer, unsigned Fraction >
SFixed<Integer, Fraction> randomSFixed(const SFixed<Integer, Fraction> & inclusiveLowerBound, const SFixed<Integer, Fraction> & exclusiveUpperBound);
#endif
FIXED_POINTS_END_NAMESPACE
//
// Definition
//
FIXED_POINTS_BEGIN_NAMESPACE
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> floorFixed(const UFixed<Integer, Fraction> & value)
{
using OutputType = UFixed<Integer, Fraction>;
using InternalType = typename OutputType::InternalType;
return OutputType::fromInternal(static_cast<InternalType>(value.getInternal() & ~OutputType::FractionMask));
}
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> floorFixed(const SFixed<Integer, Fraction> & value)
{
using OutputType = SFixed<Integer, Fraction>;
using InternalType = typename OutputType::InternalType;
return OutputType::fromInternal(static_cast<InternalType>(value.getInternal() & ~OutputType::FractionMask));
}
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> ceilFixed(const UFixed<Integer, Fraction> & value)
{
return UFixed<Integer, Fraction>((value.getFraction() == 0) ? value.getInteger() : (value.getInteger() + 1), 0);
}
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> ceilFixed(const SFixed<Integer, Fraction> & value)
{
return SFixed<Integer, Fraction>((value.getFraction() == 0) ? value.getInteger() : (value.getInteger() + 1), 0);
}
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> roundFixed(const UFixed<Integer, Fraction> & value)
{
using OutputType = UFixed<Integer, Fraction>;
return ((value.getFraction() >= OutputType(0.5).getFraction()) != 0) ? ceilFixed(value) : floorFixed(value);
}
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> roundFixed(const SFixed<Integer, Fraction> & value)
{
using OutputType = SFixed<Integer, Fraction>;
return
signbitFixed(value)
? ((value.getFraction() <= OutputType(0.5).getFraction()) != 0) ? floorFixed(value) : ceilFixed(value)
: ((value.getFraction() >= OutputType(0.5).getFraction()) != 0) ? ceilFixed(value) : floorFixed(value);
}
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> truncFixed(const UFixed<Integer, Fraction> & value)
{
return UFixed<Integer, Fraction>(value.getInteger(), 0);
}
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> truncFixed(const SFixed<Integer, Fraction> & value)
{
using OutputType = SFixed<Integer, Fraction>;
return
(value.getInternal() < 0) ?
OutputType::fromInternal(value.getInternal() & ~OutputType::FractionMask) + OutputType(1, 0) :
OutputType::fromInternal(value.getInternal() & ~OutputType::FractionMask);
}
template< unsigned Integer, unsigned Fraction >
constexpr bool signbitFixed(const SFixed<Integer, Fraction> & value)
{
return (value.getInternal() < 0);
}
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> absFixed(const SFixed<Integer, Fraction> & value)
{
return (signbitFixed(value)) ? -value : value;
}
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> copysignFixed(const SFixed<Integer, Fraction> & x, const SFixed<Integer, Fraction> & y)
{
return (signbitFixed(x) != signbitFixed(y)) ? -x : x;
}
template< unsigned Integer, unsigned Fraction >
constexpr SFixed<Integer, Fraction> nextafterFixed(const SFixed<Integer, Fraction> & from, const SFixed<Integer, Fraction> & to)
{
using ResultType = SFixed<Integer, Fraction>;
return
(from < to) ?
ResultType::fromInternal(from.getInternal() + 1) :
(from > to) ?
ResultType::fromInternal(from.getInternal() - 1):
to;
}
template< unsigned Integer, unsigned Fraction >
constexpr UFixed<Integer, Fraction> nextafterFixed(const UFixed<Integer, Fraction> & from, const UFixed<Integer, Fraction> & to)
{
using ResultType = UFixed<Integer, Fraction>;
return
(from < to) ?
ResultType::fromInternal(from.getInternal() + 1) :
(from > to) ?
ResultType::fromInternal(from.getInternal() - 1):
to;
}
//
// Unsigned Random
//
#if !defined(FIXED_POINTS_NO_RANDOM)
template< unsigned Integer, unsigned Fraction >
UFixed<Integer, Fraction> randomUFixed(void)
{
using InternalType = typename UFixed<Integer, Fraction>::InternalType;
return UFixed<Integer, Fraction>::fromInternal(FIXED_POINTS_DETAILS::RandomHelper<InternalType>::Random());
}
template< unsigned Integer, unsigned Fraction >
UFixed<Integer, Fraction> randomUFixed(const UFixed<Integer, Fraction> & exclusiveUpperBound)
{
using InternalType = typename UFixed<Integer, Fraction>::InternalType;
return UFixed<Integer, Fraction>::fromInternal(FIXED_POINTS_DETAILS::RandomHelper<InternalType>::Random() % exclusiveUpperBound.getInternal());
}
template< unsigned Integer, unsigned Fraction >
UFixed<Integer, Fraction> randomUFixed(const UFixed<Integer, Fraction> & inclusiveLowerBound, const UFixed<Integer, Fraction> & exclusiveUpperBound)
{
using InternalType = typename UFixed<Integer, Fraction>::InternalType;
return UFixed<Integer, Fraction>::fromInternal(inclusiveLowerBound.getInternal() + (FIXED_POINTS_DETAILS::RandomHelper<InternalType>::Random() % (exclusiveUpperBound.getInternal() - inclusiveLowerBound.getInternal())));
}
#endif
//
// Signed Random
//
#if !defined(FIXED_POINTS_NO_RANDOM)
template< unsigned Integer, unsigned Fraction >
SFixed<Integer, Fraction> randomSFixed(void)
{
using InternalType = typename SFixed<Integer, Fraction>::InternalType;
return SFixed<Integer, Fraction>::fromInternal(FIXED_POINTS_DETAILS::RandomHelper<InternalType>::Random());
}
template< unsigned Integer, unsigned Fraction >
SFixed<Integer, Fraction> randomSFixed(const SFixed<Integer, Fraction> & exclusiveUpperBound)
{
using InternalType = typename SFixed<Integer, Fraction>::InternalType;
return SFixed<Integer, Fraction>::fromInternal(FIXED_POINTS_DETAILS::RandomHelper<InternalType>::Random() % exclusiveUpperBound.getInternal());
}
template< unsigned Integer, unsigned Fraction >
SFixed<Integer, Fraction> randomSFixed(const SFixed<Integer, Fraction> & inclusiveLowerBound, const SFixed<Integer, Fraction> & exclusiveUpperBound)
{
using InternalType = typename SFixed<Integer, Fraction>::InternalType;
auto value = FIXED_POINTS_DETAILS::RandomHelper<InternalType>::Random();
return SFixed<Integer, Fraction>::fromInternal(inclusiveLowerBound.getInternal() + (abs(value) % (exclusiveUpperBound.getInternal() - inclusiveLowerBound.getInternal())));
}
#endif
FIXED_POINTS_END_NAMESPACE