brute_force.c
#include
#include
#include
#define CAROL_PRIME 1073676287ul
#define MERSENNE_PRIME 2147483647ul
int main()
{
unsigned long to_factor = CAROL_PRIME * MERSENNE_PRIME;
unsigned long factor1;
double largest_trial = sqrt(to_factor);
time_t begin_time, end_time;
time(&begin_time);
for (size_t ii = 3; ii < largest_trial; ii += 2)
{
if (to_factor % ii == 0)
{
printf("Factor identified: %lu \n", ii);
factor1 = ii;
break;
}
}
time(&end_time);
printf("Thus, the factorization is: %lu = %lu * %lu.\n", to_factor, factor1, to_factor / factor1);
printf("The correct factorization is: %lu = %lu * %lu.\n", to_factor, CAROL_PRIME, MERSENNE_PRIME);
printf("It took %ld seconds to find the factorization.\n", end_time - begin_time);
return 0;
}
client.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "phoenix_info.h"
#include "num_theory.h"
#include "lib.h"
/*
* Adapted by: Brian Dandurand, 5 Dec 2020.
* Based on code written by: Collin Petry and Terry Tumennasan, Nov 23, 2019
* client_lab7b.c creates a client socket, and receives server task information
* related to the task of searching for the prime factors of a large number.
* Multiple clients are envisioned, each assigned part of the search space.
*/
int read_task_info(int sockfd, uint64_t task_info[4])
{
int num_bytes = 4 * sizeof(uint64_t);
memset(task_info, 0, num_bytes); /*Set array elements to zero*/
// read the task_info data sent from the server via
// the file descriptor sockfd.
printf("Waiting for assignment from server....\n");
// in order to read the task_info data sent from the server via
// the file descriptor sockfd.
int num_bytes_read = 0; //use to store return value of read()
//read(); //reads in the number task_info
for (int i = 0; i < 4; i++)
{
uint64_t integer;
num_bytes_read += Rio_readn(sockfd, &integer, sizeof(uint64_t));
task_info[i] = be64toh(integer);
}
printf("Number of bytes read from server via fd %d is %d.\n", sockfd, num_bytes_read);
return num_bytes_read;
}
void find_factor(int sockfd, const uint64_t task_info[4])
{
uint64_t factor = 1ul;
double total_time; //in seconds
printf("Node is to test parities in \n\t{");
for (uint64_t jj = 0; jj < task_info[3]; jj++)
{
printf("%lu, ", PARITIES[task_info[3] * task_info[0] + jj]);
}
printf("\b\b}\nmodulo %lu to factor %lu\n", task_info[1], task_info[2]);
uint64_t numOfPrimes = 0ul;
uint64_t maxCheck = sqrt(task_info[2]);
uint64_t parity;
/* task_info for each node index ii includes:
task_info[ii][0] = cross-section of parity set to search
with respect to some modulus given by
task_info[ii][1] = modulus
task_info[ii][2] stores the number to be factored.
task_info[ii][3] stores the number of consecutive parities for which client is responsible
PARITIES is defined in the lab_info.h header file.*/
clock_t start_time = clock();
/*TODO: Use an OpenMP #pragma statement to parallelize this outer for loop indexed by jj
In #pragma directive, you need to specify
number of threads to use
any variables to be private (as opposed to shared)
*/
#pragma omp parallel shared(task_info, jj) private(ii, parity, PARITIES, maxCheck, factor)
{
for (uint64_t jj = 0; jj < task_info[3]; jj++)
{
parity = PARITIES[task_info[3] * task_info[0] + jj];
for (uint64_t ii = parity; ii <= maxCheck; ii += task_info[1])
{
if (task_info[2] % ii == 0)
{
if (ii != 1ul)
{
factor = ii;
}
}
}
}
}
clock_t end_time = clock();
total_time = (double)(end_time - start_time) / CLOCKS_PER_SEC;
printf("Node time to find potential divisor is: %lf seconds.\n", total_time);
/* communicate the computed candiate factor to the server
via the file descriptor sockfd.*/
printf("Waiting for server to read result....\n");
int num_bytes = 0; // Use the return value of write to assign its value
//write();
uint64_t integer;
integer = htobe64(factor);
num_bytes = Write(sockfd, &integer, sizeof(uint64_t));
printf("Number of bytes written to server via fd %d is %d.\n", sockfd, num_bytes);
printf("The value of factor found is: %lu.\n", factor);
}
/*Connects to server specified by host and portno,
Returns the file descriptor associated with the created socket.
*/
int callServer(const char *host, int portno)
{
int sockfd;
char port[10];
//ADD YOUR CODE
snprintf(port, 10, "%d", portno);
sockfd = Open_clientfd((char *)host, port);
return sockfd;
}
int main()
{
//If you change the phoenix node used as server,
// be sure to modify to the appropriate PHOENIX
_IP
int sockfd = callServer(PHOENIX0_IP, PORT);
uint64_t task_info[4];
/* reads task info from sockfd as communicated by server,
computes the factor and writes it to the sockfd to
pass back to the server. */
read_task_info(sockfd, task_info);
find_factor(sockfd, task_info);
// close the socket
close(sockfd);
return 0;
}
lib.c
#include "lib.h"
/**************************
* Error-handling functions
**************************/
/* $begin errorfuns */
/* $begin unixerror */
void unix_error(char *msg) /* Unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
/* $end unixerror */
void posix_error(int code, char *msg) /* Posix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(code));
exit(0);
}
void gai_error(int code, char *msg) /* Getaddrinfo-style error */
{
fprintf(stderr, "%s: %s\n", msg, gai_strerror(code));
exit(0);
}
void app_error(char *msg) /* Application error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
/* $end errorfuns */
void dns_error(char *msg) /* Obsolete gethostbyname error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
/*********************************************
* Wrappers for Unix process control functions
********************************************/
/* $begin forkwrapper */
pid_t Fork(void)
{
pid_t pid;
if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}
/* $end forkwrapper */
void Execve(const char *filename, char *const argv[], char *const envp[])
{
if (execve(filename, argv, envp) < 0)
unix_error("Execve error");
}
/* $begin wait */
pid_t Wait(int *status)
{
pid_t pid;
if ((pid = wait(status)) < 0)
unix_error("Wait error");
return pid;
}
/* $end wait */
pid_t Waitpid(pid_t pid, int *iptr, int options)
{
pid_t retpid;
if ((retpid = waitpid(pid, iptr, options)) < 0)
unix_error("Waitpid error");
return (retpid);
}
/* $begin kill */
void Kill(pid_t pid, int signum)
{
int rc;
if ((rc = kill(pid, signum)) < 0)
unix_error("Kill error");
}
/* $end kill */
void Pause()
{
(void)pause();
return;
}
unsigned int Sleep(unsigned int secs)
{
unsigned int rc;
if ((rc = sleep(secs)) < 0)
unix_error("Sleep error");
return rc;
}
unsigned int Alarm(unsigned int seconds)
{
return alarm(seconds);
}
void Setpgid(pid_t pid, pid_t pgid)
{
int rc;
if ((rc = setpgid(pid, pgid)) < 0)
unix_error("Setpgid error");
return;
}
pid_t Getpgrp(void)
{
return getpgrp();
}
/************************************
* Wrappers for Unix signal functions
***********************************/
/* $begin sigaction */
handler_t *Signal(int signum, handler_t *handler)
{
struct sigaction action, old_action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask); /* Block sigs of type being handled */
action.sa_flags = SA_RESTART; /* Restart syscalls if possible */
if (sigaction(signum, &action, &old_action) < 0)
unix_error("Signal error");
return (old_action.sa_handler);
}
/* $end sigaction */
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
if (sigprocmask(how, set, oldset) < 0)
unix_error("Sigprocmask error");
return;
}
void Sigemptyset(sigset_t *set)
{
if (sigemptyset(set) < 0)
unix_error("Sigemptyset error");
return;
}
void Sigfillset(sigset_t *set)
{
if (sigfillset(set) < 0)
unix_error("Sigfillset error");
return;
}
void Sigaddset(sigset_t *set, int signum)
{
if (sigaddset(set, signum) < 0)
unix_error("Sigaddset error");
return;
}
void Sigdelset(sigset_t *set, int signum)
{
if (sigdelset(set, signum) < 0)
unix_error("Sigdelset error");
return;
}
int Sigismember(const sigset_t *set, int signum)
{
int rc;
if ((rc = sigismember(set, signum)) < 0)
unix_error("Sigismember error");
return rc;
}
int Sigsuspend(const sigset_t *set)
{
int rc = sigsuspend(set); /* always returns -1 */
if (errno != EINTR)
unix_error("Sigsuspend error");
return rc;
}
/*************************************************************
* The Sio (Signal-safe I/O) package - simple reentrant output
* functions that are safe for signal handlers.
*************************************************************/
/* Private sio functions */
/* $begin sioprivate */
/* sio_reverse - Reverse a string (from K&R) */
static void sio_reverse(char s[])
{
int c, i, j;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
/* sio_ltoa - Convert long to base b string (from K&R) */
static void sio_ltoa(long v, char s[], int b)
{
int c, i = 0;
int neg = v < 0;
if (neg)
v = -v;
do
{
s[i++] = ((c = (v % b)) < 10) ? c + '0' : c - 10 + 'a';
} while ((v /= b) > 0);
if (neg)
s[i++] = '-';
s[i] = '\0';
sio_reverse(s);
}
/* sio_strlen - Return length of string (from K&R) */
static size_t sio_strlen(char s[])
{
int i = 0;
while (s[i] != '\0')
++i;
return i;
}
/* $end sioprivate */
/* Public Sio functions */
/* $begin siopublic */
ssize_t sio_puts(char s[]) /* Put string */
{
return write(STDOUT_FILENO, s, sio_strlen(s));
}
ssize_t sio_putl(long v) /* Put long */
{
char s[128];
sio_ltoa(v, s, 10); /* Based on K&R itoa() */
return sio_puts(s);
}
void sio_error(char s[]) /* Put error message and exit */
{
sio_puts(s);
_exit(1);
}
/* $end siopublic */
/*******************************
* Wrappers for the SIO routines
******************************/
ssize_t Sio_putl(long v)
{
ssize_t n;
if ((n = sio_putl(v)) < 0)
sio_error("Sio_putl error");
return n;
}
ssize_t Sio_puts(char s[])
{
ssize_t n;
if ((n = sio_puts(s)) < 0)
sio_error("Sio_puts error");
return n;
}
void Sio_error(char s[])
{
sio_error(s);
}
/********************************
* Wrappers for Unix I/O routines
********************************/
int Open(const char *pathname, int flags, mode_t mode)
{
int rc;
if ((rc = open(pathname, flags, mode)) < 0)
unix_error("Open error");
return rc;
}
ssize_t Read(int fd, void *buf, size_t count)
{
ssize_t rc;
if ((rc = read(fd, buf, count)) < 0)
unix_error("Read error");
return rc;
}
ssize_t Write(int fd, const void *buf, size_t count)
{
ssize_t rc;
if ((rc = write(fd, buf, count)) < 0)
unix_error("Write error");
return rc;
}
off_t Lseek(int fildes, off_t offset, int whence)
{
off_t rc;
if ((rc = lseek(fildes, offset, whence)) < 0)
unix_error("Lseek error");
return rc;
}
void Close(int fd)
{
int rc;
if ((rc = close(fd)) < 0)
unix_error("Close error");
}
int Select(int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
int rc;
if ((rc = select(n, readfds, writefds, exceptfds, timeout)) < 0)
unix_error("Select error");
return rc;
}
int Dup2(int fd1, int fd2)
{
int rc;
if ((rc = dup2(fd1, fd2)) < 0)
unix_error("Dup2 error");
return rc;
}
void Stat(const char *filename, struct stat *buf)
{
if (stat(filename, buf) < 0)
unix_error("Stat error");
}
void Fstat(int fd, struct stat *buf)
{
if (fstat(fd, buf) < 0)
unix_error("Fstat error");
}
/*********************************
* Wrappers for directory function
*********************************/
int Chdir(const char *path) {
int return_value;
if ((return_value = chdir(path)) == -1)
{
unix_error("chdir error");
}
return return_value;
}
DIR *Opendir(const char *name)
{
DIR *dirp = opendir(name);
if (!dirp)
unix_error("opendir...