/*
** $Id: ex_lucky.c,v 1.2 2008/03/25 04:01:21 rolf Exp $
** Rolf Riesen, March 2008
**
** Example of an emarassingly parallel problem. Determine
** the total number of "lucky" numbers in a range supplied
** on the command line. A "lucky" number is a number whose
** digits sum to 7.
*/
#include <stdio.h>
#include <stdlib.h>	/* For exit(), strtol() */
#include <mpi.h>



int
main(int argc, char *argv[])
{

int my_rank, nnodes;
int count, total_count;
long start, end;
long my_start, my_end;
int sum;
long i;
div_t q;
long share;
int debug= 0;


    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &nnodes);

    if (argc != 3)   {
	if (my_rank == 0)   {
	    fprintf(stderr, "Usage: %s start end\n", argv[0]);
	}
	exit(-1);
    }

    start= strtol(argv[1], (char **)NULL, 0);
    end= strtol(argv[2], (char **)NULL, 0);

    if ((start < 0) || (end < 0))   {
	if (my_rank == 0)   {
	    fprintf(stderr, "start (%ld) and end (%ld) must be positive\n", start, end);
	}
	exit(-1);
    }

    if (start > end)   {
	if (my_rank == 0)   {
	    fprintf(stderr, "start (%ld), must be larger than end (%ld)\n", start, end);
	}
	exit(-1);
    }

    /*
    ** Based on my rank, figure out the range I'm responsible for
    */
    share= (end - start + 1) / nnodes;
    q= div((end - start + 1), nnodes);
    my_start= my_rank * share + start;
    if (q.rem > my_rank)   {
	my_start= my_start + my_rank;
	my_end= my_start + share;
    } else   {
	my_start= my_start + q.rem;
	my_end= my_start + share - 1;
    }

    printf("[%03d] I will work on numbers %7ld through %7ld\n", my_rank, my_start, my_end);

    /*
    ** Start counting according to the rules for ID numbers
    */
    count= 0;
    for (i= my_start; i <= my_end; i++)   {
	sum= i % 9;

	if (sum == 7)   {
	    /* Found a lucky number! */
	    if (debug)   {
		printf("[%03d] %7ld is a lucky number\n", my_rank, i);
	    }
	    count++;
	}
    }

    if (debug)   {
	printf("[%03d] Found %7d lucky numbers\n", my_rank, count);
    }

    /* Combine the counts on node 0 and print */
    MPI_Reduce(&count, &total_count, 1, MPI_INT, MPI_SUM, 0,
	    MPI_COMM_WORLD);

    if (my_rank == 0)   {
	printf("In the range from %ld to %ld there are %d "
	    "lucky numbers\n", start, end, total_count);
    }


    MPI_Finalize();
    return 0;

}  /* end of main() */
