/* Copyright (c) 1997-2004
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
   http://www.math.tu-berlin.de/polymake,  mailto:polymake@math.tu-berlin.de

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
*/

namespace pm {

template <typename T>
RGB<T>::RGB(const HSV& hsv)
{
   const double Hex=hsv.hue()/60.,
                S=hsv.saturation(),
                V=hsv.value();

   const double primary=floor(Hex),
                secondary=Hex-primary,
                a=(1.-S)*V,
                b=(1.-S*secondary)*V,
                c=V+a-b,
		k=std::numeric_limits<T>::is_exact ? double(std::numeric_limits<T>::max()) : 1;

   switch (int(primary)) {
      case 0: (*this)[R]=T(k*V); (*this)[G]=T(k*c); (*this)[B]=T(k*a); break;
      case 1: (*this)[R]=T(k*b); (*this)[G]=T(k*V); (*this)[B]=T(k*a); break;
      case 2: (*this)[R]=T(k*a); (*this)[G]=T(k*V); (*this)[B]=T(k*c); break;
      case 3: (*this)[R]=T(k*a); (*this)[G]=T(k*b); (*this)[B]=T(k*V); break;
      case 4: (*this)[R]=T(k*c); (*this)[G]=T(k*a); (*this)[B]=T(k*V); break;
      case 5: (*this)[R]=T(k*V); (*this)[G]=T(k*a); (*this)[B]=T(k*b); break;
   }
}

template <typename T>
HSV::HSV(const RGB<T>& rgb)
{
   const double k=std::numeric_limits<T>::is_exact ? double(std::numeric_limits<T>::max()) : 1,
		R=rgb.red()/k,
                G=rgb.green()/k,
                B=rgb.blue()/k;

   double max=R, min=R;
   if (G>max) max=G; else min=G;
   if (B>max) max=B; else if (B<min) min=B;

   (*this)[S]=(max-min)/max;
   (*this)[V]=max;

   if ((*this)[S]) {
      if (R==max) {
	 if (G==min) {
	    (*this)[H]= B==min ? 0. : 5.+(max-B)/(max-min);
	 } else
	    (*this)[H]=1.-(max-G)/(max-min);
      } else if (G==max) {
	 if (B==min)
	    (*this)[H]=1.+(max-R)/(max-min);
	 else
	    (*this)[H]=3.-(max-B)/(max-min);
      } else {
	 if (R==min)
	    (*this)[H]=3.+(max-G)/(max-min);
	 else
	    (*this)[H]=5.-(max-R)/(max-min);
      }
      (*this)[H]*=60.;
   } else {
      (*this)[H]=0.;
   }
}

} // end namespace pm

// Local Variables:
// mode:C++
// End:
