Thanks for helpful comments.
I guess too many recursion is just bad.
I rewrite the program so that it does recursion manually.
Here is the new program.
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 1024
/*struct Pair*/
typedef struct st_node Node;
struct st_node{
char sign;
int index;
int value;
long parentOffset;
};
void Node_init(Node *node, char sign, int index, int value, long parentOffset);
void Node_print(Node *node);
void Node_init(Node *node, char sign, int index, int value, long parentOffset){
node->sign = sign;
node->index = index;
node->value = value;
node->parentOffset = parentOffset;
/*
printf("Node_init : \t");
Node_print(node);
*/
}
void Node_print(Node *node){
printf("%d,%d,%d,%d\n",node->sign,node->index,node->value,(unsigned int)node->parentOffset);
}
/*struct Stack*/
typedef struct st_stack{
Node *bottom;
Node *top;
int size;
}Stack;
void Stack_init(Stack *stack, Node node, int size);
void Stack_finish(Stack *stack);
void Stack_push(Stack *stack, Node node);
Node Stack_pop(Stack *stack);
int Stack_resize(Stack *stack, int size);
int Stack_size(Stack *stack);
void Stack_print(Stack *stack);
void Stack_init(Stack *stack, Node node, int size){
stack->bottom = stack->top = (Node*)malloc(size*sizeof(Node));
*(stack->top) = node;
stack->size = size;
}
void Stack_finish(Stack *stack){
free(stack->bottom);
stack->size = 0;
}
void Stack_push(Stack *stack, Node node){
if(stack->top - stack->bottom < stack->size-1){
*(++stack->top) = node;
}else{
if(Stack_resize(stack,2*stack->size)){
Stack_push(stack,node);
}
}
}
Node Stack_pop(Stack *stack){
if(stack->top==stack->bottom){
return *(stack->top);
}else{
return *(stack->top--);
}
}
int Stack_resize(Stack *stack, int size){
Node *nbottom = (Node*)realloc(stack->bottom,size*sizeof(Node));
if(nbottom){
printf("Stack_resize : %d\n",size);
stack->top = nbottom + (stack->top - stack->bottom);
stack->bottom = nbottom;
stack->size = size;
return 1;
}else{
printf("Stack_resize failed with size : %d\n",size);
return 0;
}
}
int Stack_size(Stack *stack){
return stack->top-stack->bottom + 1;
}
void Stack_print(Stack *stack){
printf("stack size : %d\n",Stack_size(stack));
for(Node *node=stack->bottom;node<=stack->top;node++){
Node_print(node);
}
}
int odd(int x){return ((x&1)<<1)-1;}
int sigma(int n){
int *table;
table = (int*)calloc(n,sizeof(int));
Stack stack;
Node node;
Node_init(&node,1,n,0,0);
Stack_init(&stack,node,STACK_SIZE);
int maxstack=0;
for(;;){
Node *top = stack.top;
Node *parent = stack.bottom+top->parentOffset;
long offset = top - stack.bottom;
if(top->value){
if(!table[top->index-1]){table[top->index-1]=top->value;}
if(Stack_size(&stack)>1){
parent->value += top->sign * top->value;
Stack_pop(&stack);
}else{
break;
}
}else{
if(top->index==0){
if(Stack_size(&stack)>1){
parent->value += top->sign * parent->index;
Stack_pop(&stack);
}else{
break;
}
}else if(top->index<0){
Stack_pop(&stack);
}else{
if(table[top->index-1]){
parent->value += top->sign * table[top->index-1];
Stack_pop(&stack);
}else{
/*add stack*/
for(int i=1;i*(3*i-1)<=2*top->index;i++){
Node_init(&node,odd(i),(top->index-i*(3*i-1)/2),0,offset);
Stack_push(&stack,node);
Node_init(&node,odd(i),(top->index-i*(3*i+1)/2),0,offset);
Stack_push(&stack,node);
}
}
}
}
if(maxstack<Stack_size(&stack)){maxstack=Stack_size(&stack);}
/*
for(int i=0;i<n;i++){
printf("%d,",table[i]);
}
printf("\n");
Stack_print(&stack);
*/
}
//printf("max stack size : %d\n",maxstack);
int value = stack.top->value;
Stack_finish(&stack);
free(table);
return value;
}
int main(int argc, char *argv[]){
if(argc>1){
int n = atoi(argv[1]);
printf("%d\n",sigma(n));
}
return 0;
}
I realized that recursion in this program needs a tree or something similar structure to remember the chain of function calls. I guess the original program makes the compiler build this tree on stack memory. So too many recursion caused a stack overflow.