/*
 * Scenario 5: Debug Symbols - The Missing Map
 * ============================================
 * This program has multiple functions calling each other.
 * We'll compile it with and without debug symbols to show the difference.
 *
 * Compile WITHOUT debug symbols:
 *   gcc -O2 -o nodebug program.c
 *
 * Compile WITH debug symbols:
 *   gcc -O2 -g -o withdebug program.c
 *
 * EXERCISES:
 * 1. perf record ./nodebug && perf report  (see hex addresses)
 * 2. perf record ./withdebug && perf report  (see function names)
 * 3. perf annotate -s compute_inner  (see source code!)
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* Deliberately NOT inlined to show in profiler */
__attribute__((noinline))
double compute_inner(double x, int iterations) {
    double result = x;
    for (int i = 0; i < iterations; i++) {
        result = sin(result) * cos(result) + sqrt(fabs(result));
        result = result * 1.0001 + 0.0001;
    }
    return result;
}

__attribute__((noinline))
double compute_middle(double x, int iterations) {
    double sum = 0.0;
    for (int i = 0; i < 10; i++) {
        sum += compute_inner(x + i, iterations);
    }
    return sum;
}

__attribute__((noinline))
double compute_outer(int n, int iterations) {
    double total = 0.0;
    for (int i = 0; i < n; i++) {
        total += compute_middle((double)i / n, iterations);
    }
    return total;
}

__attribute__((noinline))
void process_data(int *data, int size) {
    /* Some additional work to show in the profile */
    long sum = 0;
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < 100; j++) {
            sum += data[i] * j;
        }
    }
    printf("Data checksum: %ld\n", sum % 10000);
}

int main(int argc, char *argv[]) {
    int n = 1000;
    int iterations = 10000;
    
    if (argc > 1) n = atoi(argv[1]);
    if (argc > 2) iterations = atoi(argv[2]);
    
    printf("Running with n=%d, iterations=%d\n", n, iterations);
    
    /* Allocate some data */
    int *data = malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) {
        data[i] = i * 17 + 3;
    }
    
    /* Do some computation */
    double result = compute_outer(n, iterations);
    printf("Computation result: %f\n", result);
    
    /* Process data */
    process_data(data, n);
    
    free(data);
    return 0;
}
