/*----
    CS 111 - Homework 7 - Problem 4

    More practice compiling and running a provided (and slightly-modified)
        program using the CS50 IDE

    compile this program using:
        g++ 111hw7.cpp -o 111hw7
    run using:
        ./111hw7
    create example output using:
        ./111hw7 > 111hw7-out.txt

    adapted by: [put YOUR NAME here]
    last modified: 2025-10-20
----*/

/*--- 
    these below are a little like BSL Racket's require expressions;
    they let us use useful functions from these C++ libraries 
---*/

#include <cstdlib>
#include <iostream>
#include <string>
#include <cmath>
using namespace std;

/*---
  signature: circ_area: double -> double
  purpose: expects a circle's radius, and returns the area
      of that circle
  tests:
      circ_area(1.0) == (PI * 1.0 * 1.0)
      circ_area(2.0) == (PI * 2.0 * 2.0)
---*/

const double PI = 3.14159;

double circ_area(double radius)
{
    return PI * radius * radius;
}

/*---
  signature: check_within: double double double -> bool
  purpose: expects a function call, its expected value,
      and the maximum difference there can be between their
      values to be be considered "close enough", and returns
      true if the absolute value of the difference of
      the function call and its expected value is less than
      that maximum difference
  tests:
      check_within(sqrt(4), 2.0, 0.1) == true
      check_within(sqrt(2), 1.4, 0.001) == false

      // attempt at a a boundary test -- if equal to maximum
      //    difference, check_within will return false

      check_within(sqrt(9), 3.0, 0.0) == false
---*/

bool check_within(double funct_call, double expected_val,
                  double max_diff)
{
    return abs(funct_call - expected_val) < max_diff;
}

/*---
   test the functions above, and also print several 
       additional expressions' values to standard output.
---*/

int main()
{
    // allow boolean values to be printed correctly

    cout << boolalpha;

    cout << "*** PUT YOUR NAME HERE ***" << endl;

    cout << "*** Testing: circ_area ***" << endl;

    cout << (circ_area(1.0) == (PI * 1.0 * 1.0)) << endl;
    cout << (circ_area(2.0) == (PI * 2.0 * 2.0)) << endl;

    cout << endl;
    cout << "demo of an attempted test that fails because " << endl
         << "    double values are hard to compare exactly:" << endl;    

    cout << (circ_area(3.5) == 38.48448) << endl;

    // when a test involving double values fails,
    //     sometimes I try seeing if the actual and expected
    //     values are "close enough"

    cout << endl;
    cout << "are the expected and actual values close-enough?" << endl;

    cout << ( abs(circ_area(3.5) - 38.48448) < 0.001 ) << endl;
    cout << check_within(circ_area(3.5), 38.48448, 0.001) << endl;

    cout << "actual: " << circ_area(3.5) << endl;
    cout << "expected: " << 38.48448 << endl;

    cout << endl;
    cout << "*** Testing check_within ***" << endl;

    cout << (check_within(sqrt(4), 2.0, 0.1) == true) << endl;
    cout << (check_within(sqrt(2), 1.4, 0.001) == false) << endl;
    cout << (check_within(sqrt(9), 3.0, 0.0) == false) << endl;

    // OPTIONAL: if you would like some practice, 
    //     add additional cout statements below
    //     (but BEFORE the return statement!!)
    //     to try out printing the values of  
    //     different expressions to standard output

    return EXIT_SUCCESS;
}