# Category: Analysis
# Name: Riemann integral via Riemann sums
#
# Plot a function and then by clicking add points to the partition.  Genius
# will pick random control points in the partition and plot and compute
# the Riemann sum.  Alternatively it can be put into a mode where new partition points
# are picked automatically.
#

function f(x) = x^2+sin(5*x);
#function f(x) = x^2;
#function f(x) = 2*x*(1-x);
#function f(x) = sqrt(x)*sin(27*x);
#function f(x) = x;
#function f(x) = if x < 0.5 then -1.0 else 1.0;

limits = [0.0,1.0];

# Use midpoint rather than a random control point
usemidpoints = false;

# pick points randomly rather than by clicking
pickpointsrandomly = false;

# wait for a moment after every iteration when picking points
# randomly
waitafteriteration = true;




PlotWindowPresent(); # Make sure the window is raised

partition = limits;
c = [rand()*(limits@(2)-limits@(1))+limits@(1)];

# thousand points seems to get good results for moderately
# complicated functions
theintegral = CompositeSimpsonsRule(f, limits@(1), limits@(2), 1000);

fgraph = null;
for x = limits@(1) to limits@(2) by (limits@(2)-limits@(1))/500 do
  fgraph = [fgraph;[x,f(x)]];


while true do (
  PlotCanvasFreeze ();
  LinePlotClear ();
  
  thesum = 0.0;
  largestdeltax = 0.0;
  for n=1 to elements(partition)-1 do (
    x0 = partition@(n);
    x1 = partition@(n+1);
    deltax = x1-x0;
    if deltax > largestdeltax then largestdeltax = deltax;
    
    if usemidpoints then
      c@(n) = x0 + deltax/2.0;
      
    if elements(c) < n or c@(n) > x1 then (
      #need to pick a random control point
      c = SortVector([c,rand()*deltax+x0])
    );
    
    fc = f(c@(n));
    thesum = thesum + fc*deltax;
    
    LinePlotDrawLine([x0,0;x0,fc;x1,fc;x1,0],
                     "color", "lightgreen",
                     "filled");
    LinePlotDrawLine([x0,0;x0,fc;x1,fc;x1,0],
                     "color", "green",
                     "thickness", 2);
    LinePlotDrawLine([c@(n),0;c@(n),fc],
                     "color", "red",
                     "thickness", 1)
  );
  
  LinePlotDrawLine(fgraph,
                   "window", "fit",
                   "color", "blue",
                   "thickness", 2,
                   "legend", "f(x)");
    
  PlotCanvasThaw();
  
  print ("The riemann sum = " + thesum +
         "\nNumber of subintervals = " + elements(c) + 
         "\nLargest delta x = " + largestdeltax +
         "\nThe actual integral (approximately using Simpsons's rule) = " + theintegral + 
         "\nError = " + |thesum - theintegral| + 
         "\n");

  if pickpointsrandomly then (
    x = rand()*(limits@(2)-limits@(1)) + limits@(1);
    # Need to wait otherwise it's too fast
    if waitafteriteration then wait(0.3)
  ) else (
    p = LinePlotWaitForClick ();
    if IsNull(p) then break;
    x = p@(1)
  );
  
  if not IsIn(x,partition) and limits@(1) < x < limits@(2) then (
    partition = SortVector([partition,x])
  )
);
