import os

import inspect
import numpy as np

import logging
log = logging.getLogger("interp")

def rms(errors):
  """
    root mean square calculation
  """

  # slow pure python way for reference:
  # r = 0.0
  # for i in errors:
  #   r += np.power(i, 2)
  # r = np.sqrt(r / len(errors))
  # return r

  return np.sqrt((errors**2).mean())

def baker_exact_2D(X):
  """
    the exact function (2D) used from baker's article (for testing, slightly
    modified)
  """
  x ,y = X

  # TODO: this is not baker's function!! this is:
  #        np.power(np.sin(x*np.pi/2.0) * np.sin(y*np.pi/2.0),2)
  answer = np.power((np.sin(x * np.pi) * np.cos(y * np.pi)), 2)
  log.debug(answer)
  return answer

def friendly_exact_2D(X):
  """
    A friendlier 2D func
  """
  x ,y = X
  answer = 1.0 + x*x + y*y
  log.debug(answer)
  return answer

def baker_exact_3D(X):
  """
    the exact function (3D) used from baker's article (for testing)
  """
  x = X[0]
  y = X[1]
  z = X[2]
  answer = np.power((np.sin(x * np.pi / 2.0) * np.sin(y * np.pi / 2.0) * np.sin(z * np.pi / 2.0)), 2)
  log.debug(answer)
  return answer

def friendly_exact_3D(X):
  x,y,z = X
  return 1 + x*x + y*y + z*z

def scipy_exact_2D(X):
  x,y = X
  return x*(1-x)*np.cos(4*np.pi*x) * np.sin(4*np.pi*y**2)**2

def improved_answer(answer, exact):
  if not answer['error']:
    # was probably just a linear interpolation
    return False

  log.debug('qlin:  %s' % answer['qlin'])
  log.debug('error: %s' % answer['error'])
  log.debug('final: %s' % answer['final'])
  log.debug('exact: %s' % exact)

  if np.abs(answer['final'] - exact) <= np.abs(answer['qlin'] - exact):
    log.debug(":) improved result")
    return True
  else:
    log.debug(":( damaged result")
    return False

def improved(qlin, err, final, exact):
  if np.abs(final - exact) <= np.abs(qlin - exact):
    return True
  else:
    return False

def percent_improvement(answer, exact):
  return np.abs(answer['error']) / exact
