#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static inline double tstamp(void)
{
    struct timespec tv;
    clock_gettime(CLOCK_REALTIME, &tv);
    return tv.tv_sec + tv.tv_nsec * 1.0e-9;
}

typedef struct thread_arg
{
    long int start;
    long int limit;
    long int inc;
    long int S;
} thread_arg;

void *slice(void *arg)
{
    thread_arg *a = (thread_arg *)arg;
    long int S = 0;

    for (long int i = a->start; i <= a->limit; i = i + a->inc)
    {
        S += i;
    }
    a->S = S;
    return NULL;
}

int main(int argc, char *argv[])
{
    long int N, M, S = 0;
    thread_arg *args;
    pthread_t *ths;
    double t1, t2;

    assert(argc >= 3);
    N = strtol(argv[1], NULL, 0);
    M = strtol(argv[2], NULL, 0);
    t1 = tstamp();

    args = (thread_arg *)calloc(M, sizeof(thread_arg));
    assert(args != NULL);

    ths = (pthread_t *)calloc(M, sizeof(pthread_t));
    assert(ths != NULL);

    for (int i = 0; i < M; i++)
    {
        args[i].inc = M;
        args[i].limit = N;
        args[i].start = i + 1;
        pthread_create(ths + i, NULL, slice, (void *)(args + i));
    }

    for (int i = 0; i < M; i++)
    {
        pthread_join(ths[i], NULL);
        S += args[i].S;
    }

    assert(S == N * (N + 1) / 2);

    t2 = tstamp();
    printf("S = %ld\n", S);
    printf("t = %lf\n", t2 - t1);

    return 0;
}
