
using namespace std;
#include <stdio.h>
#include <math.h>

typedef double T;

T apply_mods(T property, const T _step, const T _scroll)  
  {
    T modprop;
    if (_step > 0) {
      T scrollval = 0;
      if(_scroll > 0) {
        // calculate scroll amount (for odometer like movement)
        T remainder  =  _step - fmod(fabs(property), _step);
        if (remainder < _scroll) {
          scrollval = (_scroll - remainder) / _scroll * _step;
        }
      }
      // apply stepping of input value
      if(property > 0)
        modprop = ((floor(property/_step) * _step) + scrollval);
      else
        modprop = ((ceil(property/_step) * _step) + scrollval);
    } else {
      modprop = property;
    }
    return modprop;
  }

T my_mods(T property, const T _step, const T _scroll)
  {
    if (_step <= 0) return property;
    T scroll(_scroll);
    if (scroll == 0) scroll = _step * 1e-6;

    double sign(1.0);
    if(property < 0) {
      property = -property;
      sign = -sign;
    }
    double quantized = _step * floor(property/_step);

    double scrollval(0.0);
    if(scroll > 0) {
      // calculate scroll amount (for odometer like movement)
      double togo = _step + quantized - property;
      if (togo < scroll) {
	scrollval = _step * (scroll - togo) / scroll;
      } 
    } 
    return sign * (quantized + scrollval);
  }

void doit(const int caseno, const T prop, const T scroll){
  fprintf(stdout, "===== Start of case %d: %20.7f %20.7f %20.7f\n", 
  	caseno, prop, 0., scroll);

  T ttl(0.);
  T my_ttl(0.);
  for (int ii = 5; ii > -5; ii--){
    T step = pow(10, ii);
    T bias = 0.;
    //bias = 0.000001;
    T rslt = apply_mods(prop+bias, step, scroll);
    T factor = .1/step;
    T final = rslt*factor;
    fprintf(stdout, "%20.7f %20.7f %20.7f %20.7f\n", 
    		rslt, final, step, scroll);
    ttl = ttl*10. + 
    	floor(10.*(.05 + final - floor(.05 + final)));

    T my_rslt = my_mods(prop+bias, step, scroll);
    T my_final = my_rslt*factor;
    char* flag = "*";
    if (fabs(final - my_final) > .0001) flag = "!";
    fprintf(stdout, "%20.7f %20.7f%s%20.7f %20.7f\n", 
    		my_rslt, my_final, flag, step, scroll);
		
    my_ttl = my_ttl*10. + 
    	floor(10.*(.05 + my_final - floor(.05 + my_final)));
  }
  ttl /= 1e4;
  char* status = "OK";
  if (fabs(ttl - prop) > .00001) status = "BAD";
  fprintf(stdout, "Old case %d: %15.7f %s\n", caseno, ttl, status);


  my_ttl /= 1e4;
  status = "OK";
  if (fabs(my_ttl - prop) > .00001) status = "BAD";
  fprintf(stdout, "My  case %d: %15.7f %s\n", caseno, my_ttl, status);
}

int main(int argc, char** argv){
  T prop = 12345.;
  prop += 9./10.;
  prop += 9./100.;
  prop += 1./1000.;
  doit(1, prop, .00001);
  doit(2, prop, -1.);
  doit(3, prop, 0.);
  prop = 12345.;
  prop += 3./10.;
  doit(4, prop, .00001);
  doit(5, prop, -1.);
  doit(6, prop, 0.);
}

#if 0

find . | Xargs grep -Il '<bias'
./Aircraft/Citation-Bravo/Models/Bravo.xml
./Aircraft/f15c/f15c.xml
./Aircraft/Instruments-3d/ky196/ky196-comm2.xml
./Aircraft/Instruments-3d/ky196/ky196-comm1.xml
./Aircraft/Instruments-3d/kap140/KAP140TwoAxisAlt.xml
./Aircraft/Instruments-3d/VIR-32/ctl32-nav1.xml
./Aircraft/Instruments-3d/VIR-32/ctl32-nav2.xml
./Aircraft/Instruments-3d/kns80/kns80.xml
./Aircraft/Instruments-3d/ADF-462/ctl62-adf.xml
./Aircraft/Instruments-3d/VHF-22/ctl22-com1.xml
./Aircraft/Instruments-3d/VHF-22/ctl22-com2.xml
./Aircraft/mirage2000/mirage2000.xml
./Aircraft/f18/f18.xml
./Aircraft/f16/f16.xml
./Aircraft/f16/f16at.xml

#endif
