constexpr base case not considered during compilation - c++

I was trying out the constexpr functions and stumbled upon the below example of implementing Fibonacci numbers
There is no logical difference between fibon2 and fibon1 but I still get the compilation error of exceeding template initializations for the fibon1.
What i'm missing here?
#include <cstdint>
#include <iostream>
template <int32_t x>
constexpr int32_t fibon2() {
if constexpr (x == 0)
return 1;
else if constexpr (x == 1)
return 1;
else if constexpr (x == 2)
return 1;
else
return fibon2<x - 1>() + fibon2<x - 2>();
}
template <int32_t x>
constexpr int32_t fibon1() {
if constexpr (x == 0) return 1;
if constexpr (x == 1) return 1;
if constexpr (x == 2) return 1;
return fibon1<x - 1>() + fibon1<x - 2>();
}
int32_t fibon3(int32_t x) {
if (x == 1) return 1;
if (x == 2) return 1;
return fibon3(x - 1) + fibon3(x - 2);
}
int main() {
std::cout << fibon3(2) << std::endl;
std::cout << fibon2<2>() << std::endl;
std::cout << fibon1<2>() << std::endl;
return 0;
}

The return in fibon1 is not under constexpr and thus has to be compiled regardless of the template argument provided.
Clang show this nicely: https://godbolt.org/z/577f15Kv1
If you put the return inside its own if constexpr then your fibon1 will compile:
template <int32_t x>
constexpr int32_t fibon1() {
if constexpr (x == 0) return 1;
if constexpr (x == 1) return 1;
if constexpr (x == 2) return 1;
if constexpr (x > 2)
return fibon1<x - 1>() + fibon1<x - 2>();
}

The last return in fibon2 is in a constexpr-if even though there's only an else there. It's the same as if you'd made it:
else if constexpr (x == 2)
return 1;
else if constexpr(true) // <- like this
return fibon2<x - 1>() + fibon2<x - 2>();
That's not the case in fibon1 which is why it fails. If you want a freestanding if constexpr for it, then
template <int32_t x>
constexpr int32_t fibon1() {
if constexpr (x == 0) return 1; // shouldn't this be 0 ?
if constexpr (x == 1) return 1;
if constexpr (x == 2) return 1; // this doesn't seem correct if fibon1<0> => 1
// added constexpr-if:
if constexpr (x < 0 || x > 2) return fibon1<x - 1>() + fibon1<x - 2>();
}
Note that the above will fail if you supply a negative value as a template parameter as it will never reach one of your terminating conditions. Either the recursion will be to deep or you'll get a signed integer overflow. If you instead want symmetry around 0, you can simply negate the template parameter and return value in case the template parameter is negative:
template <int32_t x>
constexpr int32_t fibon1() {
if constexpr (x < 0)
return -fibon1<-x>(); // like this
else if constexpr (x == 0 || x == 1) // assuming you want 0 for input 0
return x;
else
return fibon1<x - 1>() + fibon1<x - 2>();
}

Related

Looking for nbit adder in c++

I was trying to build 17bit adder, when overflow occurs it should round off should appear just like int32.
eg: In int32 add, If a = 2^31 -1
int res = a+1
res= -2^31-1
Code I tried, this is not working & is there a better way. Do I need to convert decimal to binary & then perform 17bit operation
int addOvf(int32_t result, int32_t a, int32_t b)
{
int max = (-(0x01<<16))
int min = ((0x01<<16) -1)
int range_17bit = (0x01<<17);
if (a >= 0 && b >= 0 && (a > max - b)) {
printf("...OVERFLOW.........a=%0d b=%0d",a,b);
}
else if (a < 0 && b < 0 && (a < min - b)) {
printf("...UNDERFLOW.........a=%0d b=%0d",a,b);
}
result = a+b;
if(result<min) {
while(result<min){ result=result + range_17bit; }
}
else if(result>min){
while(result>max){ result=result - range_17bit; }
}
return result;
}
int main()
{
int32_t res,x,y;
x=-65536;
y=-1;
res =addOvf(res,x,y);
printf("Value of x=%0d y=%0d res=%0d",x,y,res);
return 0;
}
You have your constants for max/min int17 reversed and off by one. They should be
max_int17 = (1 << 16) - 1 = 65535
and
min_int17 = -(1 << 16) = -65536.
Then I believe that max_int_n + m == min_int_n + (m-1) and min_int_n - m == max_int_n - (m-1), where n is the bit count and m is some integer in [min_int_n, ... ,max_int_n]. So putting that all together the function to treat two int32's as though they are int17's and add them would be like
int32_t add_as_int17(int32_t a, int32_t b) {
static const int32_t max_int17 = (1 << 16) - 1;
static const int32_t min_int17 = -(1 << 16);
auto sum = a + b;
if (sum < min_int17) {
auto m = min_int17 - sum;
return max_int17 - (m - 1);
} else if (sum > max_int17) {
auto m = sum - max_int17;
return min_int17 + (m - 1);
}
return sum;
}
There is probably some more clever way to do that but I believe the above is correct, assuming I understand what you want.

The next prime number

Among the given input of two numbers, check if the second number is exactly the next prime number of the first number. If so return "YES" else "NO".
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int nextPrime(int x){
int y =x;
for(int i=2; i <=sqrt(y); i++){
if(y%i == 0){
y = y+2;
nextPrime(y);
return (y);
}
}
return y;
}
int main()
{
int n,m, x(0);
cin >> n >> m;
x = n+2;
if(n = 2 && m == 3){
cout << "YES\n";
exit(0);
}
nextPrime(x) == m ? cout << "YES\n" : cout << "NO\n";
return 0;
}
Where is my code running wrong? It only returns true if next number is either +2 or +4.
Maybe it has something to do with return statement.
I can tell you two things you are doing wrong:
Enter 2 4 and you will check 4, 6, 8, 10, 12, 14, 16, 18, ... for primality forever.
The other thing is
y = y+2;
nextPrime(y);
return (y);
should just be
return nextPrime(y + 2);
Beyond that your loop is highly inefficient:
for(int i=2; i <=sqrt(y); i++){
Handle even numbers as special case and then use
for(int i=3; i * i <= y; i += 2){
Using a different primality test would also be faster. For example Miller-Rabin primality test:
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
#include <bit>
// square and multiply algorithm for a^d mod n
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) __builtin_unreachable();
unsigned shift = std::countl_zero(d) + 1;
uint32_t t = a;
int32_t m = d << shift;
for (unsigned i = 32 - shift; i > 0; --i) {
t = ((uint64_t)t * t) % n;
if (m < 0) t = ((uint64_t)t * a) % n;
m <<= 1;
}
return t;
}
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
uint32_t x = pow_n(a, d, n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u};
static const std::array bounds{
2'047u, 1'373'653u, 25'326'001u, 3'215'031'751u, UINT_MAX
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
And yes, that is an awful lot of code but it runs very few times.
Something to do with the return statement
I would say so
y = y+2;
nextPrime(y);
return (y);
can be replaced with
return nextPrime(y + 2);
Your version calls nextPrime but fails to do anything with the return value, instead it just returns y.
It would be more usual to code the nextPrime function with another loop, instead of writing a recursive function.

Nested static loop fails to work due to constexpr uncapturable

I have this static_loop construct that is used for type dispatching over loop unrolling.
template <std::size_t n, typename F> void static_loop(F&& f) {
static_assert(n <= 8 && "static loop size should <= 8");
if constexpr (n >= 8)
f(std::integral_constant<size_t, n - 8>());
if constexpr (n >= 7)
f(std::integral_constant<size_t, n - 7>());
if constexpr (n >= 6)
f(std::integral_constant<size_t, n - 6>());
if constexpr (n >= 5)
f(std::integral_constant<size_t, n - 5>());
if constexpr (n >= 4)
f(std::integral_constant<size_t, n - 4>());
if constexpr (n >= 3)
f(std::integral_constant<size_t, n - 3>());
if constexpr (n >= 2)
f(std::integral_constant<size_t, n - 2>());
if constexpr (n >= 1)
f(std::integral_constant<size_t, n - 1>());
}
template <typename T> constexpr size_t tupleSize(T) { return tuple_size_v<T>; }
struct A {
int a;
int b;
void run() {
auto ab = std::make_tuple(std::ref(a), std::ref(b));
static_loop<2>([&](auto i) {
std::get<i>(ab) = i;
static_loop<2>([&](auto j) { std::get<i * j>(ab) = i; });
// static_loop<2>([&, i = std::integral_constant<size_t, i>()](auto j) { std::get<i * j>(ab) = i; });
});
std::cout << a << " " << b << std::endl;
}
};
However it doesn't compile when doing nested loops. I'd assume i and j are both constexpr thus i * j is valid in std::get<>, however, compiler seems not allowing this. Is it possible to capture i as constexpr in the inner lambda?
Full example is at godbolt along with the error messages.
static_loop<2>([&](auto i) {
std::get<i>(ab) = i;
static_loop<2>([&](auto j) { std::get<i * j>(ab) }
}
The IDE correctly underlines the error for you. i * jis a multiplication of two variables, it is not a compile-time constant.
You can nest loops if you switch to template parameters rather than function arguments.
This somehow works. Not sure if it violates any standard rules.
template <std::size_t n, typename F> void static_loop(F&& f) {
static_assert(n <= 8 && "static loop size should <= 8");
if constexpr (n >= 8)
f(std::integral_constant<size_t, n - 8>());
if constexpr (n >= 7)
f(std::integral_constant<size_t, n - 7>());
if constexpr (n >= 6)
f(std::integral_constant<size_t, n - 6>());
if constexpr (n >= 5)
f(std::integral_constant<size_t, n - 5>());
if constexpr (n >= 4)
f(std::integral_constant<size_t, n - 4>());
if constexpr (n >= 3)
f(std::integral_constant<size_t, n - 3>());
if constexpr (n >= 2)
f(std::integral_constant<size_t, n - 2>());
if constexpr (n >= 1)
f(std::integral_constant<size_t, n - 1>());
}
struct A {
int a;
int b;
void run() {
auto ab = std::make_tuple(std::ref(a), std::ref(b));
static_loop<2>([&](auto i) {
std::get<i>(ab) = i;
static_loop<2>([&](auto j) { auto ii = decltype(i)(); std::get<ii * j>(ab) = ii; });
});
std::cout << a << " " << b << std::endl;
}
};
The captured value might not be constexpr but its type is somehow retained.

Calculate the function F(n) with recursion

Read the topic that I do not know what it is saying:
The function F (n) determined on non-negative integers as follows:
F (0) = 1; F (1) = 1; F (2n) = f (n); F (2n + 1) = F (n) + F (n + 1)
Calculated F (n) by recursion.
and my code:
#include<iostream.h>
double TINH_F(int n)
{
if(n == 0)
{
return 0;
}
if(n == 1)
{
return 1;
}
return (F(n+1) - F(2*n+1));
}
This is obviously incorrect. A recursive function calls itself and includes a stopping condition:
#include<iostream.h>
double TINH_F(int n)
{
if(n == 0)
{
return 0;
}
if(n == 1)
{
return 1;
}
// Note the function name change
return (TINH_F(n+1) - TINH_F(2*n+1));
}
What should your function do if the integer passed in is negative? Will the recursion still work? Or should you throw an exception to indicate to callers that the contract is broken?
int f(int n)
{
if (n<0) return -1; // check if n is positive
if (n<=1) return 1; // we can catch the first two cases in a single condition
int half = n/2;
if (n % 2 == 0) return f(half); // if n is even
else return f(half) + f(half+1); // if n is odd
}
Your last case says
F (n) = F (n+1) + F(2 * n + 1), for all n > 1
If you read the definition carefully, this case is not mentioned anywhere.
I believe you're being tricked by the naming of the parameter - you need four cases.
Let's break it down:
F (0) = 1 (or 0 - your definition says 1, but the code says 0...)
F (1) = 1
F (2n) = F (n)
F (2n + 1) = F (n) + F (n + 1)
The first two cases are trivial.
The third case says that if the argument - let's call it m - is even, the result is F(m/2).
The fourth case says that if the argument m is odd, the result is F(m/2) + F(m/2 + 1).
(Confirming the arithmetic left as an exercise.)
In C++:
unsigned int TINH_F(unsigned int n)
{
if(n == 0)
{
return 1;
}
else if(n == 1)
{
return 1;
}
else if (n % 2 == 0)
{
return TINH_F(n / 2);
}
else
{
return TINH_F(n/2) + TINH_F(n/2 + 1);
}
}

malloc.c:2451: sYSMALLOc: Assertion ... failed

I cannot for the life of me figure out what's going on. Here's the error I get:
alloc static vecs
a.out: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed. Aborted (core dumped)
The error occurs in the function Halton in class qmc, which I've included the relevant bits to below. As you can see, the first print statement "alloc static vecs" executes, but the statement std::vector<double> H(s); appears not to, since the print statement immediately following it does not execute.
Now, I should mention that when I replace the statement static std::vector<int> bases = FirstPrimes(s); in Halton with static std::vector<int> bases = {2,3,5,7,11,13}; (the RHS is the return array of FirstPrimes(), just hardcoded) then there is no error.
There are more functions in Halton (it returns a std::vector) but I've omitted them for brevity. I'll add them if anyone wants to try to run it themselves, just ask!
I'm using g++ 4.6 and Ubuntu 12.04, and the compilation command is g++ -std=c++0x scratch.cpp QMC.cpp.
main (scratch.cpp):
#include <iostream>
#include <vector>
#include "QMC.h"
int main() {
QMC qmc;
std::vector<double> halton = qmc.Halton(6,1);
}
QMC.h:
#ifndef QMC_H
#define QMC_H
#include <iostream>
#include <cmath>
#include <vector>
class QMC {
public:
QMC();
bool isPrime(int n);
std::vector<int> ChangeBase(int n, int radix);
std::vector<int> NextChangeBase(std::vector<int>& a_in, int radix);
double RadicalInverse(std::vector<int>& a, int b);
std::vector<int> FirstPrimes(int n);
std::vector<double> Halton(int s, int n = 0);
};
#endif
QMC.cpp:
#include "QMC.h"
QMC::QMC(){}
std::vector<double> QMC::Halton(int s, int n) {
static std::vector<std::vector<int> > newBases(s);
static std::vector<int> bases = FirstPrimes(s);
/* replacing the statement immediately above with
static std::vector<int> bases = {2,3,5,7,11,13}; fixes it */
std::cout << "alloc static vecs \n";
std::vector<double> H(s);
std::cout << "alloc H \n";
// ...there's more to this function, but the error occurs just above this.
}
std::vector<int> QMC::FirstPrimes(int n) {
std::vector<int> primes(n);
primes[0] = 2;
int testNum = 3;
for (int countOfPrimes = 1; countOfPrimes <= n; ++countOfPrimes) {
while (isPrime(testNum) == false)
testNum = testNum + 2;
primes[countOfPrimes] = testNum;
testNum = testNum + 2;
}
return primes;
}
bool QMC::isPrime(int n) {
if (n == 1) return false; // 1 is not prime
else if (n < 4) return true; // 2 & 3 are prime
else if (n % 2 == 0) return false; // even numbers are not prime
else if (n < 9) return true; // 5 & 7 are prime
else if (n % 3 == 0) return false; // multiples of 3 (> 3) are not prime
else
{
int r = floor(sqrt((double)n));
int f = 5;
while (f <= r)
{
if (n % f == 0) return false;
if (n % (f + 2) == 0) return false;
f += 6;
}
return true;
}
}
FirstPrimes has a buffer overflow. The relevant lines:
std::vector<int> primes(n);
primes[0] = 2;
for (int countOfPrimes = 1; countOfPrimes <= n; ++countOfPrimes)
primes[countOfPrimes] = testNum;
For a vector of size n, the valud indices are 0 through n-1. On the last loop iteration you do an out-of-bounds access.
I'd suggest changing both of the [ ] to .at( ), as well as fixing the logic error. This would also prevent trouble if you happened to call this function with n == 0.