// Must declare the main assembly entry point before use.
void main_asm();
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "pico/float.h" // Required for using single-precision variable
#include "pico/double.h" // Required for using double-precision variables
#include "pico/multicore.h" // Required for using multiple cores on the RP2040.
#define WOKWI // Uncomment if running on Wokwi RP2040 emulator
#define PI 3.14159265359
#define MAX_ITERATIONS 100000
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Function to calculate pi using the Wallis product, using single-precision floating-point
* representation
*
* This function estimates the value of PI using the Wallis algorithm. It iteratively computes
* the product of fractions based on the Wallis formula and uses this to optimize Pi. This
* function uses single-precision floating-point representation
*
* @return the calculated value of PI
*
*/
float single_precision(int iterations) {
// Starting timestamp
uint64_t startingTime = time_us_64();
float pi = 1.0;
for (int i = 1; i <= iterations; i++) {
float numerator = 4.0f * i * i;
float denominator = numerator - 1.0f;
pi = pi * (numerator / denominator);
}
pi = pi * 2.0; // why did i have this here lol
// Timestmp of finished operations
uint64_t finishedTime= time_us_64();
//Total time is the time differance
float differance= (finishedTime- startingTime)/ 1000.0f;
printf ("Time taken for calculation of single precision Wallis float calculations: %f miliseconds\n", differance);
return pi;
}
/**
* @brief Function to calculate pi using the Wallis product, using double-precision floating-point
* representation
*
* This function estimates the value of PI using the Wallis algorithm. It iteratively computes
* the product of fractions based on the Wallis formula and uses this to optimize Pi. This
* function uses double- precision floating-point representation
*
* @return the calculated value of PI
*
*/
double double_precision(int iterations) {
//Starting time
uint64_t startingTime= time_us_64();
double pi = 1.0;
for (int i = 1; i <= iterations; i++) {
double numerator = 4.0 * i * i;
double denominator = numerator - 1;
pi = pi * (numerator / denominator);
}
pi = pi * 2.0;
//Time finished operations
uint64_t finishingTime= time_us_64();
// Time taken is differance between the two
float differance= (finishingTime- startingTime)/ 1000.0f;
printf ("Time taken for calculation of double precision Wallis float calculations: %f miliseconds\n", differance);
return pi;
}
/**
* @brief
*
*This function acts as the main entry-point for core #1.
*A function pointer is passed in via the FIFO with one
*incoming int32_t used as a parameter. The function will
*provide an int32_t return value by pushing it back on
*the FIFO, which also indicates that the result is ready.
*/
// Required for using single-precision variables. // Required for using double-precision variables.
void core1_entry() { while (1) {
//
int32_t (*func)() = (int32_t(*)()) multicore_fifo_pop_blocking();
int32_t p = multicore_fifo_pop_blocking();
int32_t result = (*func)(p);
multicore_fifo_push_blocking(result);
}
}
/**
* @brief Main function that outputs the values to the serial monitor
*
* This is the main function of the program. It calls the Wallis functions and calculates
* the approximate error between these results and the defined PI. It submits these results
* to the serial monitor.
*
* @return always returns 0.
*/
int main() {
const int ITER_MAX = 100000;
stdio_init_all();
multicore_launch_core1(core1_entry);
float singlePI = single_precision();
float comparedSingle = PI - singlePI;
double doublePI = double_precision();
double comparedDouble = PI - doublePI;
// Print a console message to inform user what's going on.
printf("Calculated value of PI using single-precision = %f\n", singlePI);
printf("Approximation error = %f\n", comparedSingle);
printf("Calculated value of PI using double-precision = %lf\n", doublePI);
printf("Approximation error = %lf\n", comparedDouble);
// Returning zero indicates everything went okay.
return 0;
}