/*****
* runtime.in
* Tom Prince 2005/4/15
*
* Generate the runtime functions used by the vm::stack machine.
*
*****/

/* Autogenerated routines are specified like this (separated by a formfeed):
  type asyname:cname(cparams)
  {
  C code
  }

*/

// Use Void f() instead of void f() to force an explicit Stack argument.


pen      => primPen()
pair     => primPair()
triple   => primTriple()
path     => primPath()
path3     => primPath3()
guide*   => primGuide()
cycleToken => primCycleToken()
tensionSpecifier => primTensionSpecifier()
curlSpecifier => primCurlSpecifier()
file*    => primFile()
picture* => primPicture()
transform => primTransform()
callable* => voidFunction()
runnable* => primCode()
boolarray* => booleanArray()
Intarray*  => IntArray()
Intarray2*  => IntArray2()
realarray* => realArray()
realarray2* => realArray2()
pairarray* => pairArray()
pairarray2* => pairArray2()
triplearray* => tripleArray()
triplearray2* => tripleArray2()
patharray* => pathArray()
patharray2* => pathArray2()
guidearray* => guideArray()
transformarray* => transformArray()
penarray* => penArray()
penarray2* => penArray2()
stringarray* => stringArray()
stringarray2* => stringArray2()

#include <cfloat>
#include <iostream>
#include <fstream>
#include <time.h>

#include <chrono>
#include <thread>

#if !defined(_WIN32)
#include <sys/times.h>
#endif

#include <locale.h>
#include "angle.h"
#include "pair.h"
#include "triple.h"
#include "transform.h"
#include "path.h"
#include "path3.h"
#include "pen.h"
#include "drawpath.h"
#include "guide.h"
#include "picture.h"
#include "fileio.h"
#include "genv.h"
#include "builtin.h"
#include "texfile.h"
#include "pipestream.h"
#include "asyparser.h"
#include "stack.h"
#include "util.h"
#include "locate.h"
#include "mathop.h"
#include "callable.h"
#include "stm.h"
#include "lexical.h"
#include "asyprocess.h"
#include "arrayop.h"
#include "seconds.h"

#if defined(USEGC) && defined(GC_DEBUG) && defined(GC_BACKTRACE)
 extern "C" {
   void *GC_generate_random_valid_address(void);
   void GC_debug_print_heap_obj_proc(void *);
 }
#endif

using namespace vm;
using namespace camp;
using namespace settings;
using namespace utils;

#undef OUT
#undef IN

namespace run {
using camp::pair;
using vm::array;
using vm::vmFrame;
using vm::stack;
using camp::transform;
using absyntax::runnable;

typedef array boolarray;
typedef array Intarray;
typedef array Intarray2;
typedef array realarray;
typedef array realarray2;
typedef array pairarray;
typedef array pairarray2;
typedef array triplearray;
typedef array triplearray2;
typedef array patharray;
typedef array patharray2;
typedef array guidearray;
typedef array transformarray;
typedef array penarray;
typedef array penarray2;
typedef array stringarray;
typedef array stringarray2;
}

using vm::array;
using types::function;

#define PRIMITIVE(name,Name,asyName) using types::prim##Name;
#include <primitives.h>
#undef PRIMITIVE

using types::booleanArray;
using types::IntArray;
using types::IntArray2;
using types::realArray;
using types::realArray2;
using types::pairArray;
using types::pairArray2;
using types::tripleArray;
using types::tripleArray2;
using types::pathArray;
using types::pathArray2;
using types::guideArray;
using types::transformArray;
using types::penArray;
using types::penArray2;
using types::stringArray;
using types::stringArray2;
using types::formal;

function *realRealFunction()
{
 return new function(primReal(),primReal());
}

function *realTripleFunction()
{
 return new function(primReal(),primTriple());
}

const size_t camp::ColorComponents[]={0,0,1,3,4,0};

namespace vm {
#if COMPACT
const Int DefaultValue=0x7fffffffffffffffLL;
const Int Undefined=0x7ffffffffffffffeLL;

const Int BoolTruthValue=0xABABABABABABABACLL;
const Int BoolFalseValue=0xABABABABABABABABLL;

const item Default=DefaultValue;
#else
const item Default=item(default_t());
#endif
}

namespace run {

stopWatch wallClock;
cpuTimer cpuTime;

const char *arrayempty="cannot take min or max of empty array";
const char *noruntime="no runtime environment for embedded eval";

void writestring(stack *s)
{
 callable *suffix=pop<callable *>(s,NULL);
 string S=pop<string>(s);
 vm::item it=pop(s);
 bool defaultfile=isdefault(it);
 camp::file *f=defaultfile ? &camp::Stdout : vm::get<camp::file*>(it);
 if(!f->isOpen() || !f->enabled()) return;
 if(S != "" || f->isBinary() || f->isXDR()) f->write(S);
 if(f->text()) {
   if(suffix) {
     s->push(f);
     suffix->call(s);
   } else if(defaultfile) f->writeline();
 }
}

string toplocation()
{
 ostringstream buf;
 position& topPos=processData().topPos;
 buf << topPos.Line() << "." << topPos.Column();
 return buf.str();
}

string emptystring;
pair zero;

}

static string defaulttransparency=string("Compatible");

void unused(void *)
{
}

// Autogenerated routines:



// Initializers

Int :IntZero()
{
 return 0;
}

real :realZero()
{
 return 0.0;
}

bool :boolFalse()
{
 return false;
}

bool isnan(real x)
{
 return std::isnan(x);
}

array* :pushNullArray()
{
 return 0;
}

vmFrame* :pushNullRecord()
{
 return 0;
}

item :pushNullFunction()
{
 return nullfunc::instance();
}


// Default operations

// Put the default value token on the stack (in place of an argument when
// making a function call).
item :pushDefault()
{
 return Default;
}


// Test if the value on the stack is the default value token.
bool :isDefault(item i)
{
 return isdefault(i);
}


// Casts

guide* :pairToGuide(pair z)
{
 return new pairguide(z);
}

guide* :pathToGuide(path p)
{
 return new pathguide(p);
}

path :guideToPath(guide *g)
{
 return g->solve();
}


// Pen operations

pen :newPen()
{
 return pen();
}

bool ==(pen a, pen b)
{
 return a == b;
}

bool !=(pen a, pen b)
{
 return a != b;
}

pen +(pen a, pen b)
{
 return a+b;
}

pen Operator *(real a, pen b)
{
 return a*b;
}

pen Operator *(pen a, real b)
{
 return b*a;
}

pair max(pen p)
{
 return p.bounds().Max();
}

pair min(pen p)
{
 return p.bounds().Min();
}

// Reset the meaning of pen default attributes.
void resetdefaultpen()
{
 processData().defaultpen=camp::pen::initialpen();
}

void defaultpen(pen p)
{
 processData().defaultpen=pen(resolvepen,p);
}

pen defaultpen()
{
 return processData().defaultpen;
}

bool invisible(pen p)
{
 return p.invisible();
}

pen invisible()
{
 return pen(invisiblepen);
}

pen gray(pen p)
{
 p.togrey();
 return p;
}

pen rgb(pen p)
{
 p.torgb();
 return p;
}

pen cmyk(pen p)
{
 p.tocmyk();
 return p;
}

pen interp(pen a, pen b, real t)
{
 return interpolate(a,b,t);
}

pen rgb(real r, real g, real b)
{
 return pen(r,g,b);
}

pen cmyk(real c, real m, real y, real k)
{
 return pen(c,m,y,k);
}

pen gray(real gray)
{
 return pen(gray);
}

realarray *colors(pen p)
{
 size_t n=ColorComponents[p.colorspace()];
 array *a=new array(n);

 switch(n) {
   case 0:
     break;
   case 1:
     (*a)[0]=p.gray();
     break;
   case 3:
     (*a)[0]=p.red();
     (*a)[1]=p.green();
     (*a)[2]=p.blue();
     break;
   case 4:
     (*a)[0]=p.cyan();
     (*a)[1]=p.magenta();
     (*a)[2]=p.yellow();
     (*a)[3]=p.black();
     break;
   default:
     break;
 }
 return a;
}

string hex(pen p)
{
 return p.hex();
}

Int byte(real x)
{
 return camp::byte(x);
}

real byteinv(Int x)
{
 return x >= 0 ? camp::byteinv(x) : 0.0;
}

string colorspace(pen p)
{
 string s=ColorDeviceSuffix[p.colorspace()];
 std::transform(s.begin(),s.end(),s.begin(),tolower);
 return s;
}

pen pattern(string *s)
{
 return pen(setpattern,*s);
}

string pattern(pen p)
{
 return p.fillpattern();
}

pen fillrule(Int n)
{
 return pen(n >= 0 && n < nFill ? (FillRule) n : DEFFILL);
}

Int fillrule(pen p)
{
 return p.Fillrule();
}

pen opacity(real opacity=1.0, string blend=defaulttransparency)
{
 for(Int i=0; i < nBlendMode; ++i)
   if(blend == BlendMode[i]) return pen(Transparency(blend,opacity));

 ostringstream buf;
 buf << "Unknown blend mode: " << "'" << blend << "'";
 error(buf);
}

real opacity(pen p)
{
 return p.opacity();
}

string blend(pen p)
{
 return p.blend();
}

pen linetype(realarray *pattern, real offset=0, bool scale=true,
            bool adjust=true)
{
 size_t size=checkArray(pattern);
 array *a=new array(size);
 for(size_t i=0; i < size; ++i)
   (*a)[i]=::max(vm::read<double>(pattern,i),0.0);

 return pen(LineType(*a,offset,scale,adjust));
}

realarray *linetype(pen p=CURRENTPEN)
{
 array a=p.linetype()->pattern;
 return copyArray(&a);
}

real offset(pen p)
{
 return p.linetype()->offset;
}

bool scale(pen p)
{
 return p.linetype()->scale;
}

bool adjust(pen p)
{
 return p.linetype()->adjust;
}

pen adjust(pen p, real arclength, bool cyclic)
{
 return adjustdash(p,arclength,cyclic);
}

pen linecap(Int n)
{
 return pen(setlinecap,n >= 0 && n < nCap ? n : DEFCAP);
}

Int linecap(pen p=CURRENTPEN)
{
 return p.cap();
}

pen linejoin(Int n)
{
 return pen(setlinejoin,n >= 0 && n < nJoin ? n : DEFJOIN);
}

Int linejoin(pen p=CURRENTPEN)
{
 return p.join();
}

pen miterlimit(real x)
{
 return pen(setmiterlimit,x >= 1.0 ? x : DEFJOIN);
}

real miterlimit(pen p=CURRENTPEN)
{
 return p.miter();
}

pen linewidth(real x)
{
 return pen(setlinewidth,x >= 0.0 ? x : DEFWIDTH);
}

real linewidth(pen p=CURRENTPEN)
{
 return p.width();
}

pen fontcommand(string *s)
{
 return pen(setfont,*s);
}

string font(pen p=CURRENTPEN)
{
 return p.Font();
}

pen fontsize(real size, real lineskip)
{
 return pen(setfontsize,size > 0.0 ? size : 0.0,
            lineskip > 0.0 ? lineskip : 0.0);
}

real fontsize(pen p=CURRENTPEN)
{
 return p.size();
}

real lineskip(pen p=CURRENTPEN)
{
 return p.Lineskip();
}

pen overwrite(Int n)
{
 return pen(setoverwrite,n >= 0 && n < nOverwrite ? (overwrite_t) n :
            DEFWRITE);
}

Int overwrite(pen p=CURRENTPEN)
{
 return p.Overwrite();
}

pen basealign(Int n)
{
 return pen(n >= 0 && n < nBaseLine ? (BaseLine) n : DEFBASE);
}

Int basealign(pen p=CURRENTPEN)
{
 return p.Baseline();
}

transform transform(pen p)
{
 return p.getTransform();
}

path nib(pen p)
{
 return p.Path();
}

pen makepen(path p)
{
 return pen(p);
}

pen colorless(pen p)
{
 p.colorless();
 return p;
}

// Interactive mode

bool interactive()
{
 return interact::interactive;
}

bool uptodate()
{
 return interact::uptodate;
}


// System commands

Int system(stringarray *s)
{
 if(safe) error("system() call disabled; override with option -nosafe");
 size_t size=checkArray(s);
 if(size == 0) return 0;
 mem::vector<string> cmd;
 for(size_t i=0; i < size; ++i)
   cmd.push_back(read<string>(s,i));
 return System(cmd);
}

bool view()
{
 return view();
}

string asydir()
{
 return systemDir;
}

string locale(string s=emptystring)
{
 char *L=setlocale(LC_ALL,s.empty() ? NULL : s.c_str());
 return L != NULL ? string(L) : "";
}

void abort(string s=emptystring)
{
 if(s.empty()) throw handled_error();
 error(s.c_str());
}

void exit()
{
 throw quit();
}

void assert(bool b, string s=emptystring)
{
 flush(cout);
 if(!b) {
   ostringstream buf;
   buf << "assert FAILED";
   if(s != "") buf << ": " << s;
   error(buf);
 }
}

void sleep(Int seconds)
{
 if(seconds <= 0) return;
 std::this_thread::sleep_for(std::chrono::seconds(seconds));
}

void usleep(Int microseconds)
{
 if(microseconds <= 0) return;
 std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
}

void _eval(string *s, bool embedded, bool interactiveWrite=false)
{
 if(embedded) {
   trans::coenv *e=Stack->getEnvironment();
   vm::interactiveStack *is=dynamic_cast<vm::interactiveStack *>(Stack);
   if(e && is)
     runStringEmbedded(*s, *e, *is);
   else
     error(noruntime);
 } else
   runString(*s,interactiveWrite);
}

void _eval(runnable *s, bool embedded)
{
 absyntax::block *ast=new absyntax::block(s->getPos(), false);
 ast->add(s);

 if(embedded) {
   trans::coenv *e=Stack->getEnvironment();
   vm::interactiveStack *is=dynamic_cast<vm::interactiveStack *>(Stack);
   if(e && is)
     runCodeEmbedded(ast, *e, *is);
   else
     error(noruntime);
 } else
   runCode(ast);
}

string xasyKEY() {
 processDataStruct& P=processData();
 xkey_t& xkey=P.xkey;
 xkey_t::iterator p=xkey.find(P.topPos.LineColumn());
 if(settings::keys)
   return p != xkey.end() ? p->second : toplocation();
 else
   return p != xkey.end() ? p->second+" 1" : toplocation()+" 0";
}

void xasyKEY(string *s) {
 processData().KEY=*s;
}

string location() {
 ostringstream buf;
 buf << getPos();
 return buf.str();
}

// Wrapper for the stack::loadModule() method.
void :loadModule(string *index, Int numPushedParents)
{
 Stack->loadModule(*index, numPushedParents);
}

string cd(string s=emptystring)
{
 if(!globalread()) readDisabled();
 if(!s.empty() && !globalwrite()) {
   string outname=settings::outname();
   string dir=stripFile(outname);
   if(dir.empty()) Setting("outname")=getPath()+dirsep+outname;
 }
 return setPath(s.c_str());
}

void list(string *s, bool imports=false)
{
 if(*s == "-") return;
 trans::genv ge;
 symbol name=symbol::trans(*s);
 record *r=ge.getModule(name,*s);
 r->e.list(imports ? 0 : r);
}


// Guide operations

guide* :nullGuide()
{
 return new pathguide(path());
}

guide* :dotsGuide(guidearray *a)
{
 guidevector v;
 size_t size=checkArray(a);
 for (size_t i=0; i < size; ++i)
   v.push_back(a->read<guide*>(i));

 return new multiguide(v);
}

guide* :dashesGuide(guidearray *a)
{
 static camp::curlSpec curly;
 static camp::specguide curlout(&curly, camp::OUT);
 static camp::specguide curlin(&curly, camp::IN);

 size_t n=checkArray(a);

 // a--b is equivalent to a{curl 1}..{curl 1}b
 guidevector v;
 if (n > 0)
   v.push_back(a->read<guide*>(0));

 if (n==1) {
   v.push_back(&curlout);
   v.push_back(&curlin);
 }
 else
   for (size_t i=1; i<n; ++i) {
     v.push_back(&curlout);
     v.push_back(&curlin);
     v.push_back(a->read<guide*>(i));
   }

 return new multiguide(v);
}

cycleToken :newCycleToken()
{
 return cycleToken();
}

guide *operator cast(cycleToken tok)
{
// Avoid unused variable warning messages.
 unused(&tok);
 return new cycletokguide();
}

guide* operator spec(pair z, Int p)
{
 camp::side d=(camp::side) p;
 camp::dirSpec *sp=new camp::dirSpec(z);

 return new specguide(sp,d);
}

curlSpecifier operator curl(real gamma, Int p)
{
 camp::side s=(camp::side) p;
 return curlSpecifier(gamma,s);
}

real :curlSpecifierValuePart(curlSpecifier spec)
{
 return spec.getValue();
}

Int :curlSpecifierSidePart(curlSpecifier spec)
{
 return spec.getSide();
}

guide *operator cast(curlSpecifier spec)
{
 return new specguide(spec);
}

tensionSpecifier operator tension(real tout, real tin, bool atleast)
{
 return tensionSpecifier(tout, tin, atleast);
}

real :tensionSpecifierOutPart(tensionSpecifier t)
{
 return t.getOut();
}

real :tensionSpecifierInPart(tensionSpecifier t)
{
 return t.getIn();
}

bool :tensionSpecifierAtleastPart(tensionSpecifier t)
{
 return t.getAtleast();
}

guide *operator cast(tensionSpecifier t)
{
 return new tensionguide(t);
}

guide* operator controls(pair zout, pair zin)
{
 return new controlguide(zout, zin);
}

Int size(guide *g)
{
 flatguide f;
 g->flatten(f,false);
 return f.size();
}

Int length(guide *g)
{
 flatguide f;
 g->flatten(f,false);
 return g->cyclic() ? f.size() : f.size()-1;
}

bool cyclic(guide *g)
{
 flatguide f;
 g->flatten(f,false);
 return g->cyclic();
}

pair point(guide *g, Int t)
{
 flatguide f;
 g->flatten(f,false);
 return f.Nodes(adjustedIndex(t,f.size(),g->cyclic())).z;
}

pairarray *dirSpecifier(guide *g, Int t)
{
 flatguide f;
 g->flatten(f,false);
 Int n=f.size();
 if(!g->cyclic() && (t < 0 || t >= n-1)) return new array(0);
 array *c=new array(2);
 (*c)[0]=f.Nodes(t).out->dir();
 (*c)[1]=f.Nodes(t+1).in->dir();
 return c;
}

pairarray *controlSpecifier(guide *g, Int t)
{
 flatguide f;
 g->flatten(f,false);
 Int n=f.size();
 if(!g->cyclic() && (t < 0 || t >= n-1)) return new array(0);
 knot curr=f.Nodes(t);
 knot next=f.Nodes(t+1);
 if(curr.out->controlled()) {
   assert(next.in->controlled());
   array *c=new array(2);
   (*c)[0]=curr.out->control();
   (*c)[1]=next.in->control();
   return c;
 } else return new array(0);
}

tensionSpecifier tensionSpecifier(guide *g, Int t)
{
 flatguide f;
 g->flatten(f,false);
 Int n=f.size();
 if(!g->cyclic() && (t < 0 || t >= n-1)) return tensionSpecifier(1.0,1.0,false);
 knot curr=f.Nodes(t);
 return tensionSpecifier(curr.tout.val,f.Nodes(t+1).tin.val,curr.tout.atleast);
}

realarray *curlSpecifier(guide *g, Int t)
{
 flatguide f;
 g->flatten(f,false);
 Int n=f.size();
 if(!g->cyclic() && (t < 0 || t >= n-1)) return new array(0);
 array *c=new array(2);
 real c0=f.Nodes(t).out->curl();
 real c1=f.Nodes(t+1).in->curl();
 (*c)[0]=c0 >= 0.0 ? c0 : 1.0;
 (*c)[1]=c1 >= 0.0 ? c1 : 1.0;
 return c;
}

guide *reverse(guide *g)
{
 flatguide f;
 g->flatten(f,false);
 if(f.precyclic())
   return new pathguide(g->solve().reverse());

 size_t n=f.size();
 bool cyclic=g->cyclic();
 guidevector v;
 size_t start=cyclic ? n : n-1;
 knot curr=f.Nodes(start);
 knot next=curr;
 for(size_t i=start; i > 0; --i) {
   next=f.Nodes(i-1);
   v.push_back(new pairguide(curr.z));
   if(next.out->controlled()) {
     assert(curr.in->controlled());
     v.push_back(new controlguide(curr.in->control(),next.out->control()));
   } else {
     pair d=curr.in->dir();
     if(d != zero)
       v.push_back(new specguide(new dirSpec(-d),camp::OUT));
     else {
       real C=curr.in->curl();
       if(C >= 0.0)
         v.push_back(new specguide(new curlSpec(C),camp::OUT));
     }
     real tout=curr.tin.val;
     real tin=next.tout.val;
     bool atleast=next.tout.atleast;
     if(tout != 1.0 || tin != 1.0 || next.tout.atleast)
       v.push_back(new tensionguide(tensionSpecifier(tout,tin,atleast)));
     d=next.out->dir();
     if(d != zero)
       v.push_back(new specguide(new dirSpec(-d),camp::IN));
     else {
       real C=next.out->curl();
       if(C >= 0.0)
         v.push_back(new specguide(new curlSpec(C),camp::IN));
     }
   }
   curr=next;
 }
 if(cyclic)
   v.push_back(new cycletokguide());
 else
   v.push_back(new pairguide(next.z));

 return new multiguide(v);
}


realarray *_cputime()
{
#if !defined(_WIN32)
 static const real ticktime=1.0/sysconf(_SC_CLK_TCK);
 struct tms buf;
 ::times(&buf);

 real realCutime=((real)buf.tms_cutime)*ticktime;
 real realCstime=((real)buf.tms_cstime)*ticktime;
#else
 // FIXME: See if there's a way to get cutime/cstime on windows,
 //        if it's possible.
 real realCutime=0.0;
 real realCstime=0.0;
#endif

 array *t=new array(5);
 (*t)[0]=cpuTime.seconds(); // Includes system time
 (*t)[1]=0.0;
 (*t)[2]=realCutime;
 (*t)[3]=realCstime;
 (*t)[4]=wallClock.seconds();
 return t;
}


// Transforms

bool ==(transform a, transform b)
{
 return a == b;
}

bool !=(transform a, transform b)
{
 return a != b;
}

transform +(transform a, transform b)
{
 return a+b;
}

transform Operator *(transform a, transform b)
{
 return a*b;
}

pair Operator *(transform t, pair z)
{
 return t*z;
}

path Operator *(transform t, path g)
{
 return transformed(t,g);
}

pen Operator *(transform t, pen p)
{
 return transformed(t,p);
}

picture * Operator *(transform t, picture *f)
{
 return transformed(t,f);
}

picture * Operator *(realarray2 *t, picture *f)
{
 return transformed(*t,f);
}

transform ^(transform t, Int n)
{
 transform T;
 if(n < 0) {
   n=-n;
   t=inverse(t);
 }
 for(Int i=0; i < n; i++) T=T*t;
 return T;
}

real :transformXPart(transform t)
{
 return t.getx();
}

real :transformYPart(transform t)
{
 return t.gety();
}

real :transformXXPart(transform t)
{
 return t.getxx();
}

real :transformXYPart(transform t)
{
 return t.getxy();
}

real :transformYXPart(transform t)
{
 return t.getyx();
}

real :transformYYPart(transform t)
{
 return t.getyy();
}

transform :real6ToTransform(real x, real y, real xx, real xy,
                           real yx, real yy)
{
 return transform(x,y,xx,xy,yx,yy);
}

transform shift(transform t)
{
 return transform(t.getx(),t.gety(),0,0,0,0);
}

transform shiftless(transform t)
{
 return transform(0,0,t.getxx(),t.getxy(),t.getyx(),t.getyy());
}

transform identity:transformIdentity()
{
 return identity;
}

transform inverse(transform t)
{
 return inverse(t);
}

transform shift(pair z)
{
 return shift(z);
}

transform shift(real x, real y)
{
 return shift(pair(x,y));
}

transform xscale(real x)
{
 return xscale(x);
}

transform yscale(real y)
{
 return yscale(y);
}

transform scale(real x)
{
 return scale(x);
}

transform scale(real x, real y)
{
 return scale(x,y);
}

transform slant(real s)
{
 return slant(s);
}

transform rotate(real angle, pair z=0)
{
 return rotatearound(z,radians(angle));
}

transform reflect(pair a, pair b)
{
 return reflectabout(a,b);
}

bool isometry(transform t)
{
 return t.isIsometry();
}

real bezier(real a, real b, real c, real d, real t)
{
 real onemt=1-t;
 real onemt2=onemt*onemt;
 return onemt2*onemt*a+t*(3.0*(onemt2*b+t*onemt*c)+t*t*d);
}