// ---------------------------------------------------------------------------
// - Predmth.cpp                                                             -
// - afnix:mth module - predicates implementation                            -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - 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.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2012 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Cons.hpp"
#include "Linear.hpp"
#include "Newton.hpp"
#include "Predmth.hpp"
#include "Boolean.hpp"
#include "IpPoint.hpp"
#include "Rvector.hpp"
#include "Rmatrix.hpp"
#include "Rsamples.hpp"
#include "Rpolynom.hpp"
#include "Rfunction.hpp"
#include "Exception.hpp"

namespace afnix {

  // this procedure checks that we have one argument only and returns
  // the evaluated object
  static inline Object* get_obj (Runnable* robj, Nameset* nset, Cons* args,
                                 const String& pname) {
    Object* car = nilp;
    if ((args == nilp) || (args->length () != 1))
      throw Exception ("argument-error", "illegal arguments with predicate",
                       pname);
    car = args->getcar ();
    return (car == nilp) ? nilp : car->eval (robj,nset);
  }

  // ippp: integer plane point object predicate

  Object* mth_ippp  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "i-ppoint-p");
    bool result = (dynamic_cast <IpPoint*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rsap: real samples array object predicate

  Object* mth_rsap  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "r-samples-p");
    bool result = (dynamic_cast <Rsamples*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rvip: rvi object predicate

  Object* mth_rvip  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "rvi-p");
    bool result = (dynamic_cast <Rvi*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rmip: rmi object predicate

  Object* mth_rmip  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "rmi-p");
    bool result = (dynamic_cast <Rmi*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // lnrp: linear object predicate

  Object* mth_lnrp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "linear-p");
    bool result = (dynamic_cast <Linear*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // ntwp: newton object predicate

  Object* mth_ntwp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "netwon-p");
    bool result = (dynamic_cast <Newton*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rfip: fsi object predicate
  
  Object* mth_rfip  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "rfi-p");
    bool result = (dynamic_cast <Rfi*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rvectp: rvector object predicate

  Object* mth_rvectp  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "r-vector-p");
    bool result = (dynamic_cast <Rvector*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rmtrxp: rmatrix object predicate

  Object* mth_rmtrxp  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "r-matrix-p");
    bool result = (dynamic_cast <Rmatrix*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rfuncp: rfunction object predicate

  Object* mth_rfuncp  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "r-function-p");
    bool result = (dynamic_cast <Rfunction*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rpolyp: rpolynom object predicate

  Object* mth_rpolyp  (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "r-polynom-p");
    bool result = (dynamic_cast <Rpolynom*> (obj) == nilp) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
}
