Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to check how much time passes with each 3 solutions for a problem, but sometimes I get a runtime error and can't see the passed time for 3rd solution, but sometimes it works. I think the solutions.h file is correct but i put it here anyway.
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "solutions.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
int* input1 = new int[10000];
int* input2 = new int[20000];
int* input3 = new int[40000];
int* input4 = new int[80000];
int* input5 = new int[100000];
for(int i = 0; i<100000; i++)
{
input1[i]= rand();
input2[i]= rand();
input3[i]= rand();
input4[i]= rand();
input5[i]= rand();
}
int* output1= new int[1000];
double duration;
clock_t startTime1 = clock();
solution1(input1,10000,1000,output1);
duration = 1000 * double( clock() - startTime1 ) / CLOCKS_PER_SEC;
cout << "Solution 1 with 10000 inputs took " << duration << " milliseconds." << endl;
startTime1 = clock();
solution2(input1,10000,1000,output1);
duration = 1000 * double( clock() - startTime1 ) / CLOCKS_PER_SEC;
cout << "Solution 2 with 10000 inputs took " << duration<< " milliseconds." << endl;
startTime1 = clock();
solution3(input1,10000,1000,output1);
duration = 1000 * double( clock() - startTime1 ) / CLOCKS_PER_SEC;
cout << "Solution 3 with 10000 inputs took " << duration << " milliseconds." << endl<<endl<<endl;
return 0;
}
And the solutions.h is
#ifndef SOLUTIONS_H_INCLUDED
#define SOLUTIONS_H_INCLUDED
#include <cmath>
void solution1( int input[], const int n, const int k, int output[] );
void solution2( int input[], const int n, const int k, int output[] );
void solution3( int input[], const int n, const int k, int output[] );
void swap( int &n1, int &n2 ) {
int temp = n1;
n1 = n2;
n2 = temp;
}
void solution1( int input[], const int n, const int k, int output[] ) {
int maxIndex, maxValue;
for( int i = 0; i < k; i++ ) {
maxIndex = i;
maxValue = input[i];
for( int j = i+1; j < n; j++ ) {
if( input[j] >= maxValue ) {
maxIndex = j;
maxValue = input[ j ];
}
}
swap( input[i], input[maxIndex] );
output[i] = input[i];
}
}
int partition( int input[], int p, int r ) {
int x = input[ r ], i = p - 1;
for( int j = p; j < r; j++ ) {
if( input[ j ] >= x ) {
i = i + 1;
swap( input[i], input[j] );
}
}
swap( input[i+1], input[r] );
return i + 1;
}
void quickSort( int input[], int p, int r ) {
int q;
if( p < r ) {
q = partition( input, p, r );
quickSort( input, p, q - 1 );
quickSort( input, q + 1, r );
}
}
void solution2( int input[], const int n, const int k, int output[] ) {
quickSort( input, 0, n - 1 );
for( int i = 0; i < k; i++ ) {
output[i] = input[i];
}
}
int partition2( int input[], int a, int p, int r ) {
int x = a, i = p - 1;
for( int j = p; j < r; j++ ) {
if( input[ j ] == x ) {
swap( input[ j ], input[ r ] );
}
if( input[ j ] >= x ) {
i = i + 1;
swap( input[i], input[j] );
}
}
swap( input[ i + 1 ], input[ r ] );
return i + 1;
}
void quickSort2( int input[], int p, int r ) {
int q;
if( p < r ) {
q = partition2( input, input[ r ], p, r );
quickSort2( input, p, q - 1 );
quickSort2( input, q + 1, r );
}
}
int findMin( int n1, int n2 ) {
if( n1 <= n2 )
return n1;
else
return n2;
}
int select( int input[], int n, int k, int start, int end, int flag ) {
if( n <= 5 ) {
quickSort2( input, start, end );
return input[ start + k - 1 ];
}
int i = start, numGroups = (int) ceil( ( double ) n / 5 ), numElements, j = 0;
int *medians = new int[numGroups];
while( i <= end ) {
numElements = findMin( 5, end - i + 1 );
medians[( i - start ) / 5] = select( input, numElements, (int) ceil( ( double ) numElements / 2 ), i, i + numElements - 1, 1 );
i = i + 5;
}
int M = select( medians, numGroups, (int) ceil( ( double ) numGroups / 2 ), 0, numGroups - 1, 1 );
delete[] medians;
if( flag == 1 )
return M;
int q = partition2( input, M, start, end );
int m = q - start + 1;
if( k == m )
return M;
else if( k < m )
return select( input, m - 1, k, start, q - 1, 0 );
else
return select( input, end - q, k - m, q + 1, end, 0 );
}
void solution3( int input[], const int n, const int k, int output[] ) {
select( input, n, k, 0, n - 1, 0 );
for( int i = 0; i < k; i++ )
output[i] = input[i];
}
#endif // SOLUTIONS_H_INCLUDED
Building your program with address sanitizer (clang++ clock.cxx -std=c++11 -O1 -g -fsanitize=address -fno-omit-frame-pointer) reveals the problem:
$ ./a.out
Hello world!
=================================================================
==8175==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62e00000a040 at pc 0x000104dbd912 bp 0x7fff5ae43970 sp 0x7fff5ae43968
WRITE of size 4 at 0x62e00000a040 thread T0
#0 0x104dbd911 in main clock.cxx:18
#1 0x7fff88cd85fc in start (libdyld.dylib+0x35fc)
#2 0x0 (<unknown module>)
0x62e00000a040 is located 0 bytes to the right of 40000-byte region [0x62e000000400,0x62e00000a040)
And there is your code:
int* input1 = new int[10000];
int* input2 = new int[20000];
int* input3 = new int[40000];
int* input4 = new int[80000];
int* input5 = new int[100000];
for(int i = 0; i<100000; i++)
{
input1[i]= rand();
input2[i]= rand();
input3[i]= rand();
input4[i]= rand();
input5[i]= rand();
}
As you can see, size of input1, input2, ..., input4 is 10K, 20K, 40K, 80K elements, but in the loop we are accessing to elements out of this array so this can lead to the heap corruption.
Process returned -1073741819 (0xC0000005)
This means "memory access violation" or SEGFAULT.
Hope this will help.
Related
Recently, I came across a question posted as a challenge at a competitive site. There it was asked to find the sum of all the decimal interpretation of binary representations of numbers from 1 to n. Suppose when n = 4, so, sum will be 1 + 10 + 11 + 100 = 122. Since this number could be very large so answer should be modulo 1000000007.
I came across the following solutions but was not able to optimize it.
#include<iostream>
#include<queue>
using namespace std;
int Mod(string s, int a)
{
int res = 0, i, l = s.size();
for( i = 0 ; i < l ; i++ )
{
res = ( res * 10 + s[i] - '0' ) % a;
}
return res;
}
int main()
{
int t;
cin >> t;
while(t--)
{
long long n;
cin >> n;
int Sum = 0, mod = 1000000007;
queue<string> q;
q.push("1");
while( n > 0 )
{
n--;
string s1 = q.front();
q.pop();
Sum = ( Sum + Mod(s1, mod) ) % mod;
string s2 = s1;
q.push(s1.append("0"));
q.push(s2.append("1"));
}
cout << Sum << endl;
}
return 0;
}
Constraints:
1 <= t <= 10^5, 1 <= n <= 10^18, Allowed Time = 1 sec. Any optimization help would be admirable. Thanks in advance.
After doing some calculative math finally I have come up with the solution. Thanks, to #largest_prime_is_463035818 for providing such hints. Here is my code:
#include<iostream>
#include<cmath>
#define mod 1000000007
using namespace std;
long long power(long long x, long long y)
{
long long res = 1LL;
while(y)
{
if( y & 1LL )
{
res = ( res * x ) % mod;
}
y >>= 1LL;
x = ( x * x ) % mod;
}
return res;
}
int main()
{
long long t;
cin >> t;
while(t--)
{
long long n, i, l, m, s = 0;
cin >> n;
if( n && (!( n & ( n - 1LL ) )) )
{
l = ceil(log2(n)) + 1LL;
}
else
{
l = ceil(log2(n));
}
for( i = 0LL ; i < l ; i++ )
{
if( n & ( 1LL << i ) )
{
m = ( ( ( ( n / ( 1LL << ( i + 1LL ) ) ) * ( 1LL << i ) ) + 1LL ) + ( ( n % ( 1LL << ( i + 1LL ) ) ) % ( 1LL << i ) ) );
}
else
{
m = ( ( n / ( 1LL << ( i + 1LL ) ) ) * ( 1LL << i ) );
}
s = ( s + ( ( ( m % mod ) * power(10, i) ) % mod ) ) % mod;
}
cout << s << endl;
}
return 0;
}
I was learning MO's Algorithm. In that I found a question. In which we have to make a program to take input n for n nodes of a tree then n-1 pairs of u and v denoting the connection between node u and node v. After that giving the n node values.
Then we will ask q queries. For each query we take input of k and l which denote the two nodes of that tree. Now we have to find the product of all the nodes in the path of k and l (including k and l).
I want to use MO's algorithm. https://codeforces.com/blog/entry/43230
But I am unable to make the code. Can anybody help me out in this.
The basic code for that would be:
int n, q;
int nxt[ N ], to[ N ], hd[ N ];
struct Que{
int u, v, id;
} que[ N ];
void init() {
// read how many nodes and how many queries
cin >> n >> q;
// read the edge of tree
for ( int i = 1 ; i < n ; ++ i ) {
int u, v; cin >> u >> v;
// save the tree using adjacency list
nxt[ i << 1 | 0 ] = hd[ u ];
to[ i << 1 | 0 ] = v;
hd[ u ] = i << 1 | 0;
nxt[ i << 1 | 1 ] = hd[ v ];
to[ i << 1 | 1 ] = u;
hd[ v ] = i << 1 | 1;
}
for ( int i = 0 ; i < q ; ++ i ) {
// read queries
cin >> que[ i ].u >> que[ i ].v;
que[ i ].id = i;
}
}
int dfn[ N ], dfn_, block_id[ N ], block_;
int stk[ N ], stk_;
void dfs( int u, int f ) {
dfn[ u ] = dfn_++;
int saved_rbp = stk_;
for ( int v_ = hd[ u ] ; v_ ; v_ = nxt[ v_ ] ) {
if ( to[ v_ ] == f ) continue;
dfs( to[ v_ ], u );
if ( stk_ - saved_rbp < SQRT_N ) continue;
for ( ++ block_ ; stk_ != saved_rbp ; )
block_id[ stk[ -- stk_ ] ] = block_;
}
stk[ stk_ ++ ] = u;
}
bool inPath[ N ];
void SymmetricDifference( int u ) {
if ( inPath[ u ] ) {
// remove this edge
} else {
// add this edge
}
inPath[ u ] ^= 1;
}
void traverse( int& origin_u, int u ) {
for ( int g = lca( origin_u, u ) ; origin_u != g ; origin_u = parent_of[ origin_u ] )
SymmetricDifference( origin_u );
for ( int v = u ; v != origin_u ; v = parent_of[ v ] )
SymmetricDifference( v );
origin_u = u;
}
void solve() {
// construct blocks using dfs
dfs( 1, 1 );
while ( stk_ ) block_id[ stk[ -- stk_ ] ] = block_;
// re-order our queries
sort( que, que + q, [] ( const Que& x, const Que& y ) {
return tie( block_id[ x.u ], dfn[ x.v ] ) < tie( block_id[ y.u ], dfn[ y.v ] );
} );
// apply mo's algorithm on tree
int U = 1, V = 1;
for ( int i = 0 ; i < q ; ++ i ) {
pass( U, que[ i ].u );
pass( V, que[ i ].v );
// we could our answer of que[ i ].id
}
}
This problem is a slight modification of the blog that you have shared.
Problem Tags:- MO's Algorithm, Trees, LCA, Binary Lifting, Sieve, Precomputation, Prime Factors
Precomputations:- Just we need to do some precomputations with seiveOfErothenesis to store the highest prime factor of each element possible in input constraints. Then using this we will store all the prime factors and their powers for each element in input array in another matrix.
Observation:- with the constraints you can see the there can be very few such primes possible for each element. For an element (10^6) there can be a maximum of 7 prime factors possible.
Modify MO Algo Given in blog:- Now in our compute method we just need to maintain a map that will store the current count of the prime factor. While adding or subtracting each element in solving the queries we will iterate on the prime factors of that element and divide our result(storing total no. of factors) with the old count of that prime and then update the count of that prime and the multiple our result with the new count.(This will be O(7) max for each addition/subtraction).
Complexity:- O(T * ((N + Q) * sqrt(N) * F)) where F is 7 in our case. F is the complexity of your check method().
T - no of test cases in input file.
N - the size of your input array.
Q - No. of queries.
Below is an implementation of the above approach in JAVA. computePrimePowers() and check() are the methods you would be interested in.
import java.util.*;
import java.io.*;
public class Main {
static int BLOCK_SIZE;
static int ar[];
static ArrayList<Integer> graph[];
static StringBuffer sb = new StringBuffer();
static boolean notPrime[] = new boolean[1000001];
static int hpf[] = new int[1000001];
static void seive(){
notPrime[0] = true;
notPrime[1] = true;
for(int i = 2; i < 1000001; i++){
if(!notPrime[i]){
hpf[i] = i;
for(int j = 2 * i; j < 1000001; j += i){
notPrime[j] = true;
hpf[j] = i;
}
}
}
}
static long modI[] = new long[1000001];
static void computeModI() {
for(int i = 1; i < 1000001; i++) {
modI[i] = pow(i, 1000000005);
}
}
static long pow(long x, long y) {
if (y == 0)
return 1;
long p = pow(x, y / 2);
p = (p >= 1000000007) ? p % 1000000007 : p;
p = p * p;
p = (p >= 1000000007) ? p % 1000000007 : p;
if ((y & 1) == 0)
return p;
else {
long tt = x * p;
return (tt >= 1000000007) ? tt % 1000000007 : tt;
}
}
public static void main(String[] args) throws Exception {
Reader s = new Reader();
int test = s.nextInt();
seive();
computeModI();
for(int ii = 0; ii < test; ii++){
int n = s.nextInt();
lcaTable = new int[19][n + 1];
graph = new ArrayList[n + 1];
arrPrimes = new int[n + 1][7][2];
primeCnt = new int[1000001];
visited = new int[n + 1];
ar = new int[n + 1];
for(int i = 0; i < graph.length; i++) graph[i] = new ArrayList<>();
for(int i = 1; i < n; i++){
int u = s.nextInt(), v = s.nextInt();
graph[u].add(v);
graph[v].add(u);
}
int ip = 1; while(ip <= n) ar[ip++] = s.nextInt();
computePrimePowers();
int q = s.nextInt();
LVL = new int[n + 1];
dfsTime = 0;
dfs(1, -1);
BLOCK_SIZE = (int) Math.sqrt(dfsTime);
int Q[][] = new int[q][4];
int i = 0;
while(q-- > 0) {
int u = s.nextInt(), v = s.nextInt();
Q[i][0] = lca(u, v);
if (l[u] > l[v]) {
int temp = u; u = v; v = temp;
}
if (Q[i][0] == u) {
Q[i][1] = l[u];
Q[i][2] = l[v];
}
else {
Q[i][1] = r[u]; // left at col1 in query
Q[i][2] = l[v]; // right at col2
}
Q[i][3] = i;
i++;
}
Arrays.sort(Q, new Comparator<int[]>() {
#Override
public int compare(int[] x, int[] y) {
int block_x = (x[1] - 1) / (BLOCK_SIZE + 1);
int block_y = (y[1] - 1) / (BLOCK_SIZE + 1);
if(block_x != block_y)
return block_x - block_y;
return x[2] - y[2];
}
});
solveQueries(Q);
}
System.out.println(sb);
}
static long res;
private static void solveQueries(int [][] Q) {
int M = Q.length;
long results[] = new long[M];
res = 1;
int curL = Q[0][1], curR = Q[0][1] - 1;
int i = 0;
while(i < M){
while (curL < Q[i][1]) check(ID[curL++]);
while (curL > Q[i][1]) check(ID[--curL]);
while (curR < Q[i][2]) check(ID[++curR]);
while (curR > Q[i][2]) check(ID[curR--]);
int u = ID[curL], v = ID[curR];
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
results[Q[i][3]] = res;
if (Q[i][0] != u && Q[i][0] != v) check(Q[i][0]);
i++;
}
i = 0;
while(i < M) sb.append(results[i++] + "\n");
}
static int visited[];
static int primeCnt[];
private static void check(int x) {
if(visited[x] == 1){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] -= c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
else if(visited[x] == 0){
for(int i = 0; i < 7; i++) {
int c = arrPrimes[x][i][1];
int pp = arrPrimes[x][i][0];
if(pp == 0) break;
long tem = res * modI[primeCnt[pp] + 1];
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
primeCnt[pp] += c;
tem = res * (primeCnt[pp] + 1);
res = (tem >= 1000000007) ? tem % 1000000007 : tem;
}
}
visited[x] ^= 1;
}
static int arrPrimes[][][];
static void computePrimePowers() {
int n = arrPrimes.length;
int i = 0;
while(i < n) {
int ele = ar[i];
int k = 0;
while(ele > 1) {
int c = 0;
int pp = hpf[ele];
while(hpf[ele] == pp) {
c++; ele /= pp;
}
arrPrimes[i][k][0] = pp;
arrPrimes[i][k][1] = c;
k++;
}
i++;
}
}
static int dfsTime;
static int l[] = new int[1000001], r[] = new int[1000001], ID[] = new int[1000001], LVL[], lcaTable[][];
static void dfs(int u, int p){
l[u] = ++dfsTime;
ID[dfsTime] = u;
int i = 1;
while(i < 19) {
lcaTable[i][u] = lcaTable[i - 1][lcaTable[i - 1][u]];
i++;
}
i = 0;
while(i < graph[u].size()){
int v = graph[u].get(i);
i++;
if (v == p) continue;
LVL[v] = LVL[u] + 1;
lcaTable[0][v] = u;
dfs(v, u);
}
r[u] = ++dfsTime;
ID[dfsTime] = u;
}
static int lca(int u, int v){
if (LVL[u] > LVL[v]) {
int temp = u;
u = v; v = temp;
}
int i = 18;
while(i >= 0) {
if (LVL[v] - (1 << i) >= LVL[u]) v = lcaTable[i][v];
i--;
}
if (u == v) return u;
i = 18;
while(i >= 0){
if (lcaTable[i][u] != lcaTable[i][v]){
u = lcaTable[i][u];
v = lcaTable[i][v];
}
i--;
}
return lcaTable[0][u];
}
}
// SIMILAR SOLUTION FOR FINDING NUMBER OF DISTINCT ELEMENTS FROM U TO V
// USING MO's ALGORITHM
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 40005;
const int MAXM = 100005;
const int LN = 19;
int N, M, K, cur, A[MAXN], LVL[MAXN], DP[LN][MAXN];
int BL[MAXN << 1], ID[MAXN << 1], VAL[MAXN], ANS[MAXM];
int d[MAXN], l[MAXN], r[MAXN];
bool VIS[MAXN];
vector < int > adjList[MAXN];
struct query{
int id, l, r, lc;
bool operator < (const query& rhs){
return (BL[l] == BL[rhs.l]) ? (r < rhs.r) : (BL[l] < BL[rhs.l]);
}
}Q[MAXM];
// Set up Stuff
void dfs(int u, int par){
l[u] = ++cur;
ID[cur] = u;
for (int i = 1; i < LN; i++) DP[i][u] = DP[i - 1][DP[i - 1][u]];
for (int i = 0; i < adjList[u].size(); i++){
int v = adjList[u][i];
if (v == par) continue;
LVL[v] = LVL[u] + 1;
DP[0][v] = u;
dfs(v, u);
}
r[u] = ++cur; ID[cur] = u;
}
// Function returns lca of (u) and (v)
inline int lca(int u, int v){
if (LVL[u] > LVL[v]) swap(u, v);
for (int i = LN - 1; i >= 0; i--)
if (LVL[v] - (1 << i) >= LVL[u]) v = DP[i][v];
if (u == v) return u;
for (int i = LN - 1; i >= 0; i--){
if (DP[i][u] != DP[i][v]){
u = DP[i][u];
v = DP[i][v];
}
}
return DP[0][u];
}
inline void check(int x, int& res){
// If (x) occurs twice, then don't consider it's value
if ( (VIS[x]) and (--VAL[A[x]] == 0) ) res--;
else if ( (!VIS[x]) and (VAL[A[x]]++ == 0) ) res++;
VIS[x] ^= 1;
}
void compute(){
// Perform standard Mo's Algorithm
int curL = Q[0].l, curR = Q[0].l - 1, res = 0;
for (int i = 0; i < M; i++){
while (curL < Q[i].l) check(ID[curL++], res);
while (curL > Q[i].l) check(ID[--curL], res);
while (curR < Q[i].r) check(ID[++curR], res);
while (curR > Q[i].r) check(ID[curR--], res);
int u = ID[curL], v = ID[curR];
// Case 2
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
ANS[Q[i].id] = res;
if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
}
for (int i = 0; i < M; i++) printf("%d\n", ANS[i]);
}
int main(){
int u, v, x;
while (scanf("%d %d", &N, &M) != EOF){
// Cleanup
cur = 0;
memset(VIS, 0, sizeof(VIS));
memset(VAL, 0, sizeof(VAL));
for (int i = 1; i <= N; i++) adjList[i].clear();
// Inputting Values
for (int i = 1; i <= N; i++) scanf("%d", &A[i]);
memcpy(d + 1, A + 1, sizeof(int) * N);
// Compressing Coordinates
sort(d + 1, d + N + 1);
K = unique(d + 1, d + N + 1) - d - 1;
for (int i = 1; i <= N; i++) A[i] = lower_bound(d + 1, d + K + 1, A[i]) - d;
// Inputting Tree
for (int i = 1; i < N; i++){
scanf("%d %d", &u, &v);
adjList[u].push_back(v);
adjList[v].push_back(u);
}
// Preprocess
DP[0][1] = 1;
dfs(1, -1);
int size = sqrt(cur);
for (int i = 1; i <= cur; i++) BL[i] = (i - 1) / size + 1;
for (int i = 0; i < M; i++){
scanf("%d %d", &u, &v);
Q[i].lc = lca(u, v);
if (l[u] > l[v]) swap(u, v);
if (Q[i].lc == u) Q[i].l = l[u], Q[i].r = l[v];
else Q[i].l = r[u], Q[i].r = l[v];
Q[i].id = i;
}
sort(Q, Q + M);
compute();
}
}
Demo
I am trying to implement a recurrence relation that will return me the kth term. But I am receiving the same output when I change the k value. Here is my code:
int recurrence(int a, int b, int k, int u0, int u1) {
int u = u0;
int uu = u1;
for (int i = 0; i < k; i++)
uu = a*u1 + b*u0;
return uu;
}
int recurrence2(int a1, int b1, int k1, int u4, int u5) {
int u = u4;
int uu = u5;
for (int i = 0; i < k1; i++)
uu = a1*u5 + b1*u4;
return uu;
}
int main() {
int h;
h = recurrence(7, 1, 5, 3, 5 );
int g;
g = recurrence2(17, 11, 2, 1, 2);
cout << "The result is: " << h;
cout << "The result is : " << g;
}
You evaluate the same values in expression in the loop, so result would not change regardless how many times you execute it. Looks like this is what you need:
int recurrence(int a, int b, int k, int u0, int u1)
{
for (int i = 0; i < k; i++) {
auto tmp = a*u1 + b*u0;
u0 = u1;
u1 = tmp;
}
return u1;
}
or simpler:
int recurrence(int a, int b, int k, int u0, int u1)
{
for (int i = 0; i < k; i++) {
u0 = a*u1 + b*u0;
std::swap( u1, u0 );
}
return u1;
}
second function needs to be changed the same way.
PS you asked how could you maintain state of variables for further invocations, best way is to have class that maintains it:
class Recurrence {
int m_a;
int m_b;
int m_u0;
int m_u1;
public:
Recurrence( int a, int b, int u0, int u1 ) :
m_a( a ),
m_b( b ),
m_u0( u0 ),
m_u1( u1 )
{
}
int value() const { return m_u1; }
void interate()
{
m_u0 = m_a * m_u1 + m_b * m_u0;
std::swap( m_u0, m_u1 );
}
void interateN( int n )
{
for( int i = 0; i < n; ++i ) iterate();
}
};
int main()
{
Recurence recurence( 7, 1, 3, 5 );
recurence.iterateN( 5 );
int h = recurence.value();
recurence.iterateN( 5 ); // continue
...
}
In reality you may want to have that class more generic - for example use different number of arguments, different types, store them in array etc. This code just to show you the idea.
I Have tried executing the following code in gdb, but with gdb I don`t see any segmentation fault but without gdb If I run the following code in standalone mode segmentation fault occurs. The code is related to range sum query implemented using segment tree.
#include <iostream>
#include <vector>
using namespace std;
class segmentTree
{
private:
vector<int> a;
void constructUtil(vector<int>& , int , int , int );
int queryUtil(int , int , int , int , int );
void updateUtil(int , int , int , int , int );
public:
segmentTree(vector<int> );
int query(int , int );
void update(int , int );
~segmentTree();
};
segmentTree::segmentTree(vector<int> v)
{
int n = v.size();
a.resize((2*n) - 1);
constructUtil(v, 0 , n - 1, 0);
}
segmentTree::~segmentTree()
{
a.clear();
}
void segmentTree::constructUtil(vector<int>& v, int start, int end, int i)
{
if(start == end)
{
a[i] = v[start];
}
else
{
int mid = start + ((end - start) >> 1);
constructUtil(v, start, mid, ((2*i) + 1));
constructUtil(v, mid + 1, end, ((2*i) + 2));
a[i] = a[(2*i) + 1] + a[(2*i) + 2];
}
}
int segmentTree::queryUtil(int ss, int se, int rs, int re, int i)
{
if(se < rs || re < ss)
{
return 0;
}
else if(rs <= ss && se <= re)
{
return a[i];
}
else
{
int sm = ss + ((se - ss) >> 1);
return queryUtil(ss, sm, rs, re, 2*i + 1) + queryUtil(sm + 1, se, rs, re, 2*i + 2);
}
}
int segmentTree::query(int l, int r)
{
int n = ((a.size() + 1) >> 1);
if(l < 0 || r > n-1)
{
return 0;
}
return queryUtil(0, n-1, l , r, 0);
}
void segmentTree::updateUtil(int ss, int se, int i, int si, int x)
{
if(ss > i || se < i)
{
return ;
}
else if(ss == se)
{
a[si] = x;
}
else
{
int sm = ss + ((se - ss) >> 1);
updateUtil(ss, sm, i, (2*si) + 1, x);
updateUtil(sm + 1, se, i, (2*si) + 2, x);
a[si] = a[(2*si) + 1] + a[(2*si) + 2];
}
}
void segmentTree::update(int i, int x)
{
int n = ((a.size() + 1) >> 1);
if(i < 0 || i > n-1)
{
return ;
}
else
{
updateUtil(0, n-1, i, 0, x);
}
}
int main()
{
int arr[] = {1, 3, 5, 7, 9, 11};
int n = sizeof(arr)/sizeof(arr[0]);
vector<int> v(arr, arr + n);
segmentTree st(v);
// Print sum of values in array from index 1 to 3
cout << "Sum of values in given range = " << st.query(1, 3) << endl;
// Update: set arr[1] = 10 and update corresponding
// segment tree nodes
st.update(1, 10);
// Find sum after the value is updated
cout << "Updated sum of values in given range = " << st.query(1, 3) << endl;
return 0;
}
Consider segmentTree::constructUtil with v.size() == 3. Then in the inital call to constructUtil you have start == 0 and end == 2.
Thus we get mid = 1.
In the second recursive call we are then passing start = 1, end = 2 and i = 2. start != end and so the else is executed.
However in the else block a[(2*i)+2] is accessed (by the way, no need for the parantheses there). This index will be 6.
But if you look at the size of a, it was given as 2*n-1. 2*3-1 = 5, so 6 is clearly out-of-bounds.
I don't know what your intentions with the code are, but that there is undefined behavior. You can easily catch it by either using something like valgrind, by replacing a[...] with a.at(...) for debug purposes, by stepping through the code with gdb and actually following all the variables (there does not need to be a segmentation fault for your program to have undefined behavior) or by entering debug std::cout statements with the variable content everywhere that could cause the issue.
I am implementing an algorithm to generate basis function for bsplines using the following link: http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve-coef.html
I should get a tridiagonal system on solving the system of linear equations
however I get a lower triangular matrix.
I would be glad if someone could tell me what am I am doing wrong? Thank you.
I have written computingCoefficients (b_spline_interpolation.cpp) function and I tried another function basis to compute the coeffiicents. However neither gives a tridiagonal matrix. Please help.
Here is my code
b_spline_interpolation.cpp
#include "mymain.h"
vector<double> generateParameters(int &nplus1)
{
cout<<"generating parameters.."<<endl;
size_t i= 0;//unsigned i
double n = nplus1-1;
vector<double> t(nplus1);
t[0]=0.0;
t[n]=1.0;
for(i=1;i<=n-1;i++)
t[i]=i/n;
cout<<"the parameters are:"<<endl;
for(i=0;i<t.size();i++)//print parameters
cout<<t[i]<<endl;
return t;
}
void generateKnotsUsingDeBoorFormula(int &nplus1 , int °ree_p , int &mplus1 , vector< double > &knots_u)
{
int i,j,jj,p=degree_p,n=nplus1-1,m=mplus1-1;
vector <double> t(nplus1);
t= generateParameters( nplus1 );
for( i=0;i<=p;i++)
knots_u[i]=0;
for( j= 1;j <= n-p;j++)
{
for(i = j; i<=j+p-1 ; i++)
knots_u[ j+p ]+=t[i]/p;
}
for ( jj=0;jj<=p;jj++)
knots_u[m-p+jj]=1;
cout<<"generating knots using DeBoor Formula..."<<endl;
cout<<"the knots are:"<<endl;
for(i=0;i<=m;i++)//print knots
cout<<knots_u[i]<<endl;
}
void generateUniformKnots(int nplus1 , int degree_p , int mplus1 , vector< double > &knots_u)
{ cout<<"generating knots with uniform knot spacing..."<<endl;
int i,j,jj,p=degree_p,n=nplus1-1,m=mplus1-1;
for( i=0;i<=p;i++)
knots_u[i]=0;
for( j= 1;j <= n-p;j++)
knots_u[ j+p ]=((double)j)/(n-p+1);
for ( jj=0;jj<=p;jj++)
knots_u[m-p+jj]=1;
cout<<"the knots are:"<<endl;
for(i=0;i<=m;i++)//print knots
cout<<knots_u[i]<<endl;
}
double calcDist(double x1 , double y1 , double x2 , double y2)
{double d=sqrt( pow( x1 - x2 , 2 ) +pow( y1 - y2 , 2 ));
return d;}
void generateKnotsUsingCentripetalMethod(int nplus1 , int degree_p , int mplus1 , vector< double > &knots_u,MatrixXd temp_matrix)
{ cout<<"generating knots with centripetal method..."<<endl;
int i , p = degree_p , n=nplus1-1,m=mplus1-1;
vector <double> t(nplus1);
t[ 0 ]= 0;
t[ n ]= 1;
double l = 0 ;
for(i=1;i<=n;i++) //calculating the value of L
{
l=l+calcDist(temp_matrix(i,0),temp_matrix(i,1),temp_matrix(i-1,0),temp_matrix(i-1,1) );
}
for(i=1;i<=n-1;i++)
{
t [i] = ( calcDist(temp_matrix(i,0),temp_matrix(i,1),temp_matrix(i-1,0),temp_matrix(i-1,1) ) )/l;
}
for(i=0;i<=m;i++)//print knots
cout<<knots_u[i]<<endl;
}
void computingCoefficients( int nplus1 ,int degree_p , int mplus1 , double u , vector < double > &knots_u ,vector <double> &N )//nplus1 is the number of control points of bspline curve
{
int m = mplus1 -1;
int n = nplus1 -1;
if ( u == knots_u [ 0 ]) // rule out special cases
N[0] = 1.0;
if (u == knots_u [ m ])
N[n] = 1.0 ;
if(u != knots_u[0] && u!=knots_u[m])
{
int i =0, j =0, ktemp , k =0;
for ( ktemp = 0;ktemp < m;ktemp ++ )//finding k
{
bool b1 = (u >= knots_u [ ktemp ]);
bool b2 = (u < knots_u [ ktemp+1 ]) ;
if (b1&& b2 )
k=ktemp;
}
N[k] = 1.0; // degree 0 coefficient
int degree_d = 0 ;
for (degree_d =1 ;degree_d<=degree_p;degree_d++) // degree d goes from 1 to p ,outer loop
{
if((k-degree_d>=0)&&(k-degree_d+1>=0))
N[k- degree_d ] = ( ( knots_u[ k + 1 ]-u )/( knots_u[ k + 1 ]-knots_u[ k - degree_d + 1] ) )* N[(k-degree_d)+1]; // right (south-west corner) term only
for ( i = k - degree_d + 1 ; i <= k-1 ; i++) // compute internal terms
if( ( i >= 0 )&&( i + degree_d + 1< N.size())&&( (i+1)<N.size() ) )//negative subcripts of vector give out of range vector
N[ i ] =( ( u - knots_u [ i ] )/( knots_u [ i + degree_d ] -knots_u [ i ] ) ) * N [ i ] + ( ( knots_u[ i + degree_d + 1 ]- u )/( knots_u[ i + degree_d + 1 ] - knots_u[ i + 1 ] ) ) * N[ i + 1 ];
N[ k ] = ( ( u - knots_u [ k ])/(knots_u[ k + degree_d ]-knots_u[ k ]) )* N[k]; // let (north-west corner) term only
}
}// end for this if(u != knots_u[0] && u!=knots_u[m])
cout<<"Computing Coefficients.."<<endl;
cout<<"The basis functions are:"<<endl;
for(int i=0; i<nplus1 ; i++)
cout<<N[i]<<endl;
}
void knot( int n,int c, vector<double> &x)
{cout<<"in Knot function:";
int nplusc,nplus2,i;
nplusc = n + c;
nplus2 = n + 2;
x[1] = 0;
for (i = 2; i <= nplusc; i++)
{
if ( (i > c) && (i < nplus2) )
x[i] = x[i-1] + 1;
else
x[i] = x[i-1];
}
printf("The knot vector is ");
for (i = 1; i <= nplusc; i++){
cout<<x[i]<<" ";
}
printf("\n");
}
void basis(int c , double t , int npts , vector < double > &x , vector < double > &n )
{
int nplusc;
int i,k;
double d,e;
vector <double> temp(36);
nplusc = npts + c;
printf("knot vector is \n");
for (i = 1; i <= nplusc; i++){
cout<<" "<<x[i]<<endl;
}
printf("t is %f \n", t);
/* calculate the first order basis functions n[i][1] */
for (i = 1; i<= nplusc-1; i++){
if (( t >= x[i]) && (t < x[i+1]))
temp[i] = 1;
else
temp[i] = 0;
}
/* calculate the higher order basis functions */
for (k = 2; k <= c; k++){
for (i = 1; i <= nplusc-k; i++){
if (temp[i] != 0) /* if the lower order basis function is zero skip the calculation */
d = ((t-x[i])*temp[i])/(x[i+k-1]-x[i]);
else
d = 0;
if (temp[i+1] != 0) /* if the lower order basis function is zero skip the calculation */
e = ((x[i+k]-t)*temp[i+1])/(x[i+k]-x[i+1]);
else
e = 0;
temp[i] = d + e;
}
}
if (t == (double )x[nplusc]){ /* pick up last point */
temp[npts] = 1;
}
/* put in n array */
for (i = 1; i < npts; i++) {
n[i] = temp[i];
}
}
MatrixXd getDataPoints( int &nplus1,MatrixXd &temp_matrix)//the second argument is required for centripetal spacing
{
int n=nplus1-1;
cout<<"Getting Data Points...."<<endl;
MatrixXd D=MatrixXd :: Zero( nplus1 , 2);//second argument is 2 for x,y annd 3 for x,y,z .currently in 2D
int i=0 ,j=0,k=0;
cout<< "Enter the data points:"<<endl;
for (i=0;i<=n;i++)
{ double temp[2] = {0};
for (j=0;j<1;j++)
{
cout<<"x:";
cin>>temp[j];
cout<<"y:";
cin>>temp[j+1];
cout<<endl;
D(i,j)=temp[j];
D(i,j+1)=temp[j+1];
}
}
temp_matrix =D ;//copy the matrix D into a temporary global matrix.Use this matrix in calculating knots for centripetal method
return D;
}
MatrixXd solveLinearEquation(MatrixXd &N,MatrixXd &D)
{
cout<<"solving System of Linear Equations using LU decomposition..."<<endl;
MatrixXd A =N;
MatrixXd B =D ;
MatrixXd X;
cout << "Here is the matrix A:\n" << A << endl;
cout << "Here is the right hand side b:\n" << B << endl;
X = A.ldlt().solve(B);
cout << "The solution is:\n" << X << endl;
cout << "Here is the matrix A:" << endl << A << endl;
cout << "Here is the matrix B:" << endl << B << endl;
X = A.fullPivLu().solve(B);
if((A*X).isApprox(B))
{
cout << "Here is a solution X to the equation AX = B:" << endl << X << endl;
}
else
cout << "The equation AX = B does not have any solution." << endl;
return X;
}
void computeControlPoints( int nplus1 ,int degree_p , int mplus1 , vector< double > &knots_u , int counter ,vector < double > &N ,MatrixXd &N_matrix , MatrixXd &D )
{
int n= nplus1 - 1;
//Input: n+1 n data points D0, ..... Dn and a degree p
//Output: A B-spline curve of degree p that contains all data points in the given order
int i=0,j=0,k=0;
{
for( j = 0 ; j< N_matrix.cols(); j++ )
{if (counter<N_matrix.rows())
N_matrix(counter, j ) = N[j];
}
}
if(counter==n)
{
cout << "Basis Matrix is :" << endl <<N_matrix << endl;
cout<<"Computing Control Points..."<<endl;
MatrixXd P = solveLinearEquation( N_matrix, D);
}
//Evaluate Nj,p(ti) into row i and column j of matrix N;
/* matrix N is available */
//for (i = 0 ; i< = n ; i++ )
//Place data point Di on row i of matrix D;
/* matrix D is constructed */
//Use a linear system solver to solve for P from D = N.P
//Row i of P is control point Pi;
//Control points P0, ..., Pn, knot vector U, and degree p determine an
interpolating B-spline curve;
}
mymain.h
#include <iostream>
#include<GL/glut.h>
#include<Eigen/Dense>
#include <vector>
#include<cmath>
using namespace std; // for iostream library
using namespace Eigen; // for Eigen Libary
//Function declarations
double calcDist(double x1 , double y1 , double x2 , double y2);
void knot( int n,int c, vector<double> &x);
void computeControlPoints( int nplus1 ,int degree_p , int mplus1 , vector< double > &knots_u , int counter ,vector < double > &N ,MatrixXd &N_matrix , MatrixXd &D );
void computingCoefficients( int nplus1 ,int degree_p , int mplus1 ,double u, vector < double > &knots_u ,vector <double> &N );
void drawBsplineCurve(int nplus1,int mplus1 ,MatrixXd P , vector <double> knots_u );
void generateKnotsUsingCentripetalMethod(int nplus1 , int degree_p , int mplus1 , vector< double > &knots_u,MatrixXd temp_matrix);
MatrixXd getDataPoints( int &nplus1,MatrixXd &temp_matrix);
MatrixXd solveLinearEquation(MatrixXd &N,MatrixXd &D) ;
void generateKnotsUsingDeBoorFormula(int &nplus1 , int °ree_p , int &mplus1 , vector< double > &knots_u);
vector<double> generateParameters(int &nplus1);
void generateUniformKnots(int nplus1 , int degree_p , int mplus1 , vector< double > &knots_u);
void generateKnotsUsingDeBoorFormula(int &nplus1 , int °ree_p , int &mplus1 , vector< double > &knots_u);
void basis(int c,double t,int npts,vector<double> &x,vector<double> &n);
//cubic_spline_interpolation
int spline (int n, int end1, int end2, double slope1, double slope2,
double x[], double y[], double b[], double c[], double d[],
int *iflag );
double seval (int n, double u,
double x[], double y[],
double b[], double c[], double d[],
int *last);
double sinteg (int n, double u,
double x[], double y[],
double b[], double c[], double d[],
int *last);
double deriv (int n, double u,
double x[],
double b[], double c[], double d[],
int *last);
//Display
void DisplayText(double positionx,double positiony ,int choice );
void Draw2DOrigin( double xorigin ,double yorigin );
void Draw3DOrigin(double xorigin ,double yorigin ,double zorigin);
void SelectObject(int choice);
//linear_interpolation file
void linearInterpolation(double theta1,double tx1,double ty1,double theta2,double tx2,double ty2 ,double timeparameter);
//optimization calcuation
double optimization(int choice, double a,double b , VectorXd weightsi ,VectorXd weightsj, MatrixXd A ,VectorXd q);
I am sorry for the long post. Eagerly awaiting reply!
PS: I am using Visual Studio 2008 Express Edition.
I am using Eigen Library for matrices: http://eigen.tuxfamily.org/dox/