/****************************************************************************
 * This file was derived from the CNCL library by the Pablo research group.
 *
 * The complete CNCL library is available at:
 *       http://www.comnets.rwth-aachen.de/doc/cncl.html
 *
 * The CNCL copyright notice is included here:
 *
 * |_|_|_  |_|_    |_    |_|_|_  |_               C O M M U N I C A T I O N
 *|_       |_  |_  |_  |_        |_                         N E T W O R K S
 *|_       |_  |_  |_  |_        |_                               C L A S S
 * |_|_|_  |_    |_|_    |_|_|_  |_|_|_|_                     L I B R A R Y
 *
 *
 *
 * Copyright (C) 1992-1998   Communication Networks
 *                           Aachen University of Technology
 *                           D-52056 Aachen
 *                           Germany
 *                           Email: cncl-adm@comnets.rwth-aachen.de
 *
 *
 * This library is free  software; you can  redistribute it and/or modify
 * it  under   the terms  of the GNU   Library  General Public License as
 * published by the  Free Software Foundation;  either  version 2 of  the
 * License, or  (at  your option)  any  later  version.  This  library 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 Library General Public
 * Library General Public License along with  this library; if not, write
 * to the Free Software Foundation,  675  Mass Ave, Cambridge, MA  02139,
 * USA.
 ****************************************************************************/

//   -*- C++ -*-
/*****************************************************************************
 *
 * Class: FlFSetLR --- Fuzzy set with L and R functions
 *
 *****************************************************************************/

#include "FlFSetLR.h"

#include <math.h>
#include <Flminmax.h>

using std::endl;

/*
 * Contructors
 */

FlFSetLR::FlFSetLR()
    : FlFSet(),
      m1(0), m2(0), alpha(0), beta(0), L(FlFuncLin), R(FlFuncLin)
{}


FlFSetLR::FlFSetLR(double min, double max,
		   double xm1, double xm2, double xalpha, double xbeta,
		   FlFuncType fL, FlFuncType fR                            )
    : FlFSet(min, max),
      m1(xm1), m2(xm2), alpha(xalpha), beta(xbeta), L(fL), R(fR)
{}

      
FlFSetLR::FlFSetLR(double xm1, double xm2, double xalpha, double xbeta,
		   FlFuncType fL, FlFuncType fR                            )
    : FlFSet(),
      m1(xm1), m2(xm2), alpha(xalpha), beta(xbeta), L(fL), R(fR)
{}

      
FlFSetLR::FlFSetLR(FlStringR xname, double min, double max,
		   double xm1, double xm2, double xalpha, double xbeta,
		   FlFuncType fL, FlFuncType fR                            )
    : FlFSet(xname, min, max),
      m1(xm1), m2(xm2), alpha(xalpha), beta(xbeta), L(fL), R(fR)
{}

      
FlFSetLR::FlFSetLR(FlStringR xname, 
		   double xm1, double xm2, double xalpha, double xbeta,
		   FlFuncType fL, FlFuncType fR                            )
    : FlFSet(xname),
      m1(xm1), m2(xm2), alpha(xalpha), beta(xbeta), L(fL), R(fR)
{}



/*
 * Initialize
 */
void FlFSetLR::init(FlStringR xname,
		    double xm1, double xm2, double xalpha, double xbeta,
		    FlFuncType fL, FlFuncType fR,
		    double min, double max                              )
{
    FlFSet::init(xname, min, max);
    m1    = xm1;
    m2    = xm2;
    alpha = xalpha;
    beta  = xbeta;
    L     = fL;
    R     = fR;
}


      

/*
 * Compute membership value
 */
double FlFSetLR::get_membership(double x) const
{
    double dy = ymax - ymin;

    if(x>=m1 && x<=m2)
	return ymax;
    if(x < m1)
	return ymin + dy * L((m1-x)/alpha);
    return ymin + dy * R((x-m2)/beta);
}

/*
 * 
 */
double FlFSetLR::highestPoint(double &x, double &y) const
{
  x = m1;
  y = 1;
  return m1;
}
    

/*
 * Functions
 */
double FlFuncExp(double x)
{
    if (x < 0)
	x *= -1.0;
    return exp(-x);
}

double FlFuncExp2(double x)
{
    return exp(-x*x);
}

double FlFuncLin(double x)
{
    if (x < 0)
	x *= -1.0;
    return 1-x > 0.0 ? 1-x : 0;
}

double FlFuncSqr(double x)
{
	 return Flmax(0.0, 1.0-x*x);
}

double FlFuncHyp(double x)
{
    if (x < 0)
	x *= -1.0;
    return 1 / (1+x);
}

double FlFuncHyp2(double x)
{
    return 1 / (1+x*x);
}



/***** Default I/O member function for FuzzyLib classes **************************/

// Normal output
void FlFSetLR::print(ostream &strm) const
{
    strm << "\"" << name() << "\": "  
	 << "ymin=" << ymin << " ymax=" << ymax << " m1=" << m1
	 << " m2=" << m2 << " alpha=" << alpha << " beta=" << beta << endl;
}

// Debug output
void FlFSetLR::dump(ostream &strm) const
{
    strm << "FlFSetLR { $Revision: 1.5 $" << endl;
    print(strm);
    strm << "L="  << std::hex << (unsigned long)(L)
	 << " R=" << std::hex << (unsigned long)(R) << endl
	 << "}" << endl;
}

void FlFSetLR::update(double xm1, double xm2, double xalpha, double xbeta)
{
  m1 = xm1; 
  m2 = xm2;
  alpha = xalpha;
  beta = xbeta;
}
