#ifdef HAVE_LIBFFTW3
#include "fftw++.h"
static const char *rectangular="matrix must be rectangular";
#else
static const char *installFFTW=
"Please install fftw3, then ./configure; make";
#endif
#ifdef HAVE_EIGEN_DENSE
#include <Eigen/Dense>
typedef std::complex<double> Complex;
static const char *square="matrix must be square";
using Eigen::MatrixXd;
using Eigen::MatrixXcd;
using Eigen::RealSchur;
using Eigen::ComplexSchur;
#else
static const char *installEIGEN=
"Please install eigen3, then ./configure; make";
#endif
using types::booleanArray;
using types::IntArray;
using types::IntArray2;
using types::realArray;
using types::realArray2;
using types::realArray3;
using types::pairArray;
using types::pairArray2;
using types::pairArray3;
using types::tripleArray2;
typedef callable callableReal;
void outOfBounds(const char *op, size_t len, Int n)
{
ostringstream buf;
buf << op << " array of length " << len << " with out-of-bounds index " << n;
error(buf);
}
T *A,*B;
copyArray2C(A,a,false);
copyArray2C(B,b,false);
for(size_t i=0; i < n; ++i) {
T *Ai=A+i*nb;
array *ci=new array(nb0);
(*c)[i]=ci;
for(size_t j=0; j < nb0; ++j) {
T sum=T();
size_t kj=j;
for(size_t k=0; k < nb; ++k, kj += nb0)
sum += Ai[k]*B[kj];
(*ci)[j]=sum;
}
}
delete[] B;
delete[] A;
return c;
}
// Compute transpose(A)*A where A is an n x m matrix.
template<class T>
array *AtA(array *a)
{
size_t n=checkArray(a);
size_t m=n == 0 ? 0 : checkArray(read<array*>(a,0));
array *c=new array(m);
T *A;
copyArray2C(A,a,false);
for(size_t i=0; i < m; ++i) {
array *ci=new array(m);
(*c)[i]=ci;
for(size_t j=0; j < m; ++j) {
T sum=T();
size_t kj=j;
size_t ki=i;
for(size_t k=0; k < n; ++k, kj += m, ki += m)
sum += A[ki]*A[kj];
(*ci)[j]=sum;
}
}
// Transpose an n x n matrix in place.
void transpose(double *a, size_t n)
{
for(size_t i=1; i < n; i++) {
for(size_t j=0; j < i; j++) {
size_t ij=n*i+j;
size_t ji=n*j+i;
double temp=a[ij];
a[ij]=a[ji];
a[ji]=temp;
}
}
}
// Invert an n x n array in place.
void inverse(double *M, size_t n)
{
if(n == 2) {
real a=M[0];
real b=M[1];
real c=M[2];
real d=M[3];
real det=a*d-b*c;
if(det == 0.0)
error(singular);
det=1.0/det;
M[0]=d*det;
M[1]=-b*det;
M[2]=-c*det;
M[3]=a*det;
return;
}
if(n == 3) {
real a=M[0], b=M[1], c=M[2];
real d=M[3], e=M[4], f=M[5];
real g=M[6], h=M[7], i=M[8];
real A=e*i-f*h;
real B=f*g-d*i;
real C=d*h-e*g;
real det=a*A+b*B+c*C;
if(det == 0.0)
error(singular);
det=1.0/det;
size_t col=0, row=0;
// This is the main loop over the columns to be reduced.
for(size_t i=0; i < n; i++) {
real big=0.0;
// This is the outer loop of the search for a pivot element.
for(size_t j=0; j < n; j++) {
double *aj=M+n*j;
if(pivot[j] != 1) {
for(size_t k=0; k < n; k++) {
if(pivot[k] == 0) {
real temp=fabs(aj[k]);
if(temp >= big) {
big=temp;
row=j;
col=k;
}
} else if(pivot[k] > 1) {
inverseDeallocate();
error(singular);
}
}
}
}
++(pivot[col]);
// Interchange rows, if needed, to put the pivot element on the diagonal.
double *acol=M+n*col;
if(row != col) {
double *arow=M+n*row;
for(size_t k=0; k < n; k++) {
real temp=arow[k];
arow[k]=acol[k];
acol[k]=temp;
}
}
Row[i]=row;
Col[i]=col;
// Divide the pivot row by the pivot element.
real denom=acol[col];
if(denom == 0.0) {
inverseDeallocate();
error(singular);
}
real pivinv=1.0/denom;
acol[col]=1.0;
for(size_t k=0; k < n; k++)
acol[k]=acol[k]*pivinv;
// Reduce all rows except for the pivoted one.
for(size_t k=0; k < n; k++) {
if(k != col) {
double *ak=M+n*k;
real akcol=ak[col];
ak[col]=0.0;
for(size_t j=0; j < n; j++)
ak[j] -= acol[j]*akcol;
}
}
}
// Unscramble the inverse matrix in view of the column interchanges.
for(size_t k=n; k > 0;) {
k--;
size_t r=Row[k];
size_t c=Col[k];
if(r != c) {
for(size_t j=0; j < n; j++) {
double *aj=M+n*j;
real temp=aj[r];
aj[r]=aj[c];
aj[c]=temp;
}
}
}
inverseDeallocate();
}
}
// Create a new array (technically a vector).
// This array will be multidimensional. First the number of dimensions
// is popped off the stack, followed by each dimension in reverse order.
// The array itself is technically a one dimensional array of one
// dimension arrays and so on.
#line 620 "./runarray.in"
void newDeepArray(stack *Stack)
{
Int depth=vm::pop<Int>(Stack);
#line 621 "./runarray.in"
assert(depth > 0);
Int *dims = new Int[depth];
for (Int index = depth-1; index >= 0; index--) {
Int i=pop<Int>(Stack);
if(i < 0) error("cannot create a negative length array");
dims[index]=i;
}
// Creates an array with elements already specified. First, the number
// of elements is popped off the stack, followed by each element in
// reverse order.
#line 640 "./runarray.in"
void newInitializedArray(stack *Stack)
{
Int n=vm::pop<Int>(Stack);
#line 641 "./runarray.in"
assert(n >= 0);
array *a = new array(n);
for (Int index = n-1; index >= 0; index--)
(*a)[index] = pop(Stack);
{Stack->push<array*>(a); return;}
}
// Similar to newInitializedArray, but after the n elements, append another
// array to it.
#line 654 "./runarray.in"
void newAppendedArray(stack *Stack)
{
Int n=vm::pop<Int>(Stack);
array* tail=vm::pop<array*>(Stack);
#line 655 "./runarray.in"
assert(n >= 0);
array *a = new array(n);
for (Int index = n-1; index >= 0; index--)
(*a)[index] = pop(Stack);
// Produce an array of n deep copies of value.
// typeDepth is the true depth of the array determined at compile-time when the
// operations for the array type are added. This typeDepth argument is
// automatically pushed on the stack and is not visible to the user.
#line 672 "./runarray.in"
void copyArrayValue(stack *Stack)
{
Int typeDepth=vm::pop<Int>(Stack);
Int depth=vm::pop<Int>(Stack,Int_MAX);
item value=vm::pop(Stack);
Int n=vm::pop<Int>(Stack);
#line 673 "./runarray.in"
if(n < 0) error("cannot create a negative length array");
if(depth < 0) error("cannot copy to a negative depth");
if(depth > typeDepth) depth=typeDepth;
{Stack->push<array*>(new array((size_t) n, value, depth)); return;}
}
// Deep copy of array.
// typeDepth is the true depth of the array determined at compile-time when the
// operations for the array type are added. This typeDepth argument is
// automatically pushed on the stack and is not visible to the user.
#line 684 "./runarray.in"
void copyArray(stack *Stack)
{
Int typeDepth=vm::pop<Int>(Stack);
Int depth=vm::pop<Int>(Stack,Int_MAX);
array * a=vm::pop<array *>(Stack);
#line 685 "./runarray.in"
if(a == 0) vm::error(dereferenceNullArray);
if(depth < 0) error("cannot copy to a negative depth");
if(depth > typeDepth) depth=typeDepth;
{Stack->push<array*>(a->copyToDepth(depth)); return;}
}
// Read an element from an array. Checks for initialization & bounds.
#line 693 "./runarray.in"
void arrayRead(stack *Stack)
{
Int n=vm::pop<Int>(Stack);
array * a=vm::pop<array *>(Stack);
#line 694 "./runarray.in"
item& i=arrayRead(a,n);
if (i.empty()) {
ostringstream buf;
buf << "read uninitialized value from array at index " << n;
error(buf);
}
{Stack->push(i); return;}
}
// Slice a substring from an array.
#line 705 "./runarray.in"
void arraySliceRead(stack *Stack)
{
Int right=vm::pop<Int>(Stack);
Int left=vm::pop<Int>(Stack);
array * a=vm::pop<array *>(Stack);
#line 706 "./runarray.in"
checkArray(a);
{Stack->push(a->slice(left, right)); return;}
}
// Slice a substring from an array. This implements the cases a[i:] and a[:]
// where the endpoint is not given, and assumed to be the length of the array.
#line 713 "./runarray.in"
void arraySliceReadToEnd(stack *Stack)
{
Int left=vm::pop<Int>(Stack);
array * a=vm::pop<array *>(Stack);
#line 714 "./runarray.in"
size_t len=checkArray(a);
{Stack->push(a->slice(left, (Int)len)); return;}
}
// Read an element from an array of arrays. Check bounds and initialize
// as necessary.
#line 721 "./runarray.in"
void arrayArrayRead(stack *Stack)
{
Int n=vm::pop<Int>(Stack);
array * a=vm::pop<array *>(Stack);
#line 722 "./runarray.in"
item& i=arrayRead(a,n);
if (i.empty()) i=new array(0);
{Stack->push(i); return;}
}
// Write an element to an array. Increase size if necessary.
// TODO: Add arrayWriteAndPop
#line 730 "./runarray.in"
void arrayWrite(stack *Stack)
{
item value=vm::pop(Stack);
Int n=vm::pop<Int>(Stack);
array * a=vm::pop<array *>(Stack);
#line 731 "./runarray.in"
size_t len=checkArray(a);
bool cyclic=a->cyclic();
if(cyclic && len > 0) n=imod(n,len);
else {
if(cyclic) outOfBounds("writing cyclic",len,n);
if(n < 0) outOfBounds("writing",len,n);
if(len <= (size_t) n)
a->resize(n+1);
}
(*a)[n] = value;
{Stack->push(value); return;}
}
// Check to see if an array element is initialized.
#line 797 "./runarray.in"
void arrayInitializedHelper(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
Int n=vm::pop<Int>(Stack);
#line 798 "./runarray.in"
size_t len=checkArray(a);
bool cyclic=a->cyclic();
if(cyclic && len > 0) n=imod(n,len);
else if(n < 0 || n >= (Int) len) {Stack->push<bool>(false); return;}
item&i=(*a)[(unsigned) n];
{Stack->push<bool>(!i.empty()); return;}
}
// Returns the initialize method for an array.
#line 808 "./runarray.in"
void arrayInitialized(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 809 "./runarray.in"
{Stack->push<callable*>(new thunk(new bfunc(arrayInitializedHelper),a)); return;}
}
// The helper function for the cyclic method that sets the cyclic flag.
#line 814 "./runarray.in"
void arrayCyclicHelper(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
bool b=vm::pop<bool>(Stack);
#line 815 "./runarray.in"
checkArray(a);
a->cyclic(b);
}
// Set the cyclic flag for an array.
#line 821 "./runarray.in"
void arrayCyclic(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 822 "./runarray.in"
{Stack->push<callable*>(new thunk(new bfunc(arrayCyclicHelper),a)); return;}
}
// The helper function for the push method that does the actual operation.
#line 827 "./runarray.in"
void arrayPushHelper(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
item x=vm::pop(Stack);
#line 828 "./runarray.in"
checkArray(a);
a->push(x);
{Stack->push(x); return;}
}
// Returns the push method for an array.
#line 835 "./runarray.in"
void arrayPush(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 836 "./runarray.in"
{Stack->push<callable*>(new thunk(new bfunc(arrayPushHelper),a)); return;}
}
// The helper function for the append method that appends b to a.
#line 841 "./runarray.in"
void arrayAppendHelper(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
array * b=vm::pop<array *>(Stack);
#line 842 "./runarray.in"
checkArray(a);
size_t size=checkArray(b);
for(size_t i=0; i < size; i++)
a->push((*b)[i]);
}
// Returns the append method for an array.
#line 850 "./runarray.in"
void arrayAppend(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 851 "./runarray.in"
{Stack->push<callable*>(new thunk(new bfunc(arrayAppendHelper),a)); return;}
}
// The helper function for the pop method.
#line 856 "./runarray.in"
void arrayPopHelper(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 857 "./runarray.in"
size_t asize=checkArray(a);
if(asize == 0)
error("cannot pop element from empty array");
{Stack->push(a->pop()); return;}
}
// Returns the pop method for an array.
#line 865 "./runarray.in"
void arrayPop(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 866 "./runarray.in"
{Stack->push<callable*>(new thunk(new bfunc(arrayPopHelper),a)); return;}
}
// The helper function for the insert method.
#line 871 "./runarray.in"
void arrayInsertHelper(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
array * x=vm::pop<array *>(Stack);
Int i=vm::pop<Int>(Stack);
#line 872 "./runarray.in"
size_t asize=checkArray(a);
checkArray(x);
if(a->cyclic() && asize > 0) i=imod(i,asize);
if(i < 0 || i > (Int) asize)
outOfBounds("inserting",asize,i);
(*a).insert((*a).begin()+i,(*x).begin(),(*x).end());
}
// Returns the insert method for an array.
#line 882 "./runarray.in"
void arrayInsert(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 883 "./runarray.in"
{Stack->push<callable*>(new thunk(new bfunc(arrayInsertHelper),a)); return;}
}
// Returns the delete method for an array.
#line 888 "./runarray.in"
void arrayDelete(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 889 "./runarray.in"
{Stack->push<callable*>(new thunk(new bfunc(arrayDeleteHelper),a)); return;}
}
#line 1019 "./runarray.in"
// Int sum(boolarray *a);
void gen_runarray40(stack *Stack)
{
boolarray * a=vm::pop<boolarray *>(Stack);
#line 1020 "./runarray.in"
size_t size=checkArray(a);
Int sum=0;
for(size_t i=0; i < size; i++)
sum += read<bool>(a,i) ? 1 : 0;
{Stack->push<Int>(sum); return;}
}
#line 1028 "./runarray.in"
void arrayConcat(stack *Stack)
{
array * a=vm::pop<array *>(Stack);
#line 1029 "./runarray.in"
// a is an array of arrays to be concatenated together.
// The signature is
// T[] concat(... T[][] a);
size_t numArgs=checkArray(a);
size_t resultSize=0;
for (size_t i=0; i < numArgs; ++i) {
resultSize += checkArray(a->read<array *>(i));
}
array *result=new array(resultSize);
size_t ri=0;
for (size_t i=0; i < numArgs; ++i) {
array *arg=a->read<array *>(i);
size_t size=checkArray(arg);
// a is a rectangular 3D array; perm is an Int array indicating the type of
// permutation (021 or 120, etc; original is 012).
// Transpose by sending respective members to the permutated locations:
// return the array obtained by putting a[i][j][k] into position perm{ijk}.
#line 1086 "./runarray.in"
void array3Transpose(stack *Stack)
{
array * perm=vm::pop<array *>(Stack);
array * a=vm::pop<array *>(Stack);
#line 1087 "./runarray.in"
const size_t DIM=3;
if(checkArray(perm) != DIM) {
ostringstream buf;
buf << "permutation array must have length " << DIM;
error(buf);
}
size_t* size=new size_t[DIM];
for(size_t i=0; i < DIM; ++i) size[i]=DIM;
for(size_t i=0; i < DIM; ++i) {
Int p=read<Int>(perm,i);
size_t P=(size_t) p;
if(p < 0 || P >= DIM) {
ostringstream buf;
buf << "permutation index out of range: " << p;
error(buf);
}
size[P]=P;
}
for(size_t i=0; i < DIM; ++i)
if(size[i] == DIM) error("permutation indices must be distinct");
// Find the index of the nth true value in a boolean array or -1 if not found.
// If n is negative, search backwards.
#line 1171 "./runarray.in"
// Int find(boolarray *a, Int n=1);
void gen_runarray44(stack *Stack)
{
Int n=vm::pop<Int>(Stack,1);
boolarray * a=vm::pop<boolarray *>(Stack);
#line 1172 "./runarray.in"
size_t size=checkArray(a);
Int j=-1;
if(n > 0)
for(size_t i=0; i < size; i++)
if(read<bool>(a,i)) {
n--; if(n == 0) {j=(Int) i; break;}
}
if(n < 0)
for(size_t i=size; i > 0;)
if(read<bool>(a,--i)) {
n++; if(n == 0) {j=(Int) i; break;}
}
{Stack->push<Int>(j); return;}
}
// Find all indices of true values in a boolean array.
#line 1189 "./runarray.in"
// Intarray* findall(boolarray *a);
void gen_runarray45(stack *Stack)
{
boolarray * a=vm::pop<boolarray *>(Stack);
#line 1190 "./runarray.in"
size_t size=checkArray(a);
array *b=new array(0);
for(size_t i=0; i < size; i++) {
if(read<bool>(a,i)) {
b->push((Int) i);
}
}
{Stack->push<Intarray*>(b); return;}
}
// construct vector obtained by replacing those elements of b for which the
// corresponding elements of a are false by the corresponding element of c.
#line 1203 "./runarray.in"
void arrayConditional(stack *Stack)
{
array * c=vm::pop<array *>(Stack);
array * b=vm::pop<array *>(Stack);
array * a=vm::pop<array *>(Stack);
#line 1204 "./runarray.in"
size_t size=checkArray(a);
array *r=new array(size);
if(b && c) {
checkArrays(a,b);
checkArrays(b,c);
for(size_t i=0; i < size; i++)
(*r)[i]=read<bool>(a,i) ? (*b)[i] : (*c)[i];
} else {
r->clear();
if(b) {
checkArrays(a,b);
for(size_t i=0; i < size; i++)
if(read<bool>(a,i)) r->push((*b)[i]);
} else if(c) {
checkArrays(a,c);
for(size_t i=0; i < size; i++)
if(!read<bool>(a,i)) r->push((*c)[i]);
}
}
{Stack->push<array*>(r); return;}
}
// Return an n x n identity matrix.
#line 1228 "./runarray.in"
// realarray2* identity(Int n);
void gen_runarray47(stack *Stack)
{
Int n=vm::pop<Int>(Stack);
#line 1229 "./runarray.in"
{Stack->push<realarray2*>(Identity(n)); return;}
}
// Return the inverse of an n x n matrix a using Gauss-Jordan elimination.
#line 1234 "./runarray.in"
// realarray2* inverse(realarray2 *a);
void gen_runarray48(stack *Stack)
{
realarray2 * a=vm::pop<realarray2 *>(Stack);
#line 1235 "./runarray.in"
size_t n=checkArray(a);
double *A;
copyArray2C(A,a,true,0,NoGC);
inverse(A,n);
a=copyCArray2(n,n,A);
delete[] A;
{Stack->push<realarray2*>(a); return;}
}
// Solve the linear equation ax=b by LU decomposition, returning the
// solution x, where a is an n x n matrix and b is an array of length n.
// If no solution exists, return an empty array.
#line 1248 "./runarray.in"
// realarray* solve(realarray2 *a, realarray *b, bool warn=true);
void gen_runarray49(stack *Stack)
{
bool warn=vm::pop<bool>(Stack,true);
realarray * b=vm::pop<realarray *>(Stack);
realarray2 * a=vm::pop<realarray2 *>(Stack);
#line 1249 "./runarray.in"
size_t n=checkArray(a);
for(size_t i=0; i < n; ++i) {
size_t ip=index[i];
real sum=B[ip];
B[ip]=B[i];
real *Ai=A+i*n;
for(size_t j=0; j < i; ++j)
sum -= Ai[j]*B[j];
B[i]=sum;
}
for(size_t i=n; i > 0;) {
--i;
real sum=B[i];
real *Ai=A+i*n;
for(size_t j=i+1; j < n; ++j)
sum -= Ai[j]*B[j];
B[i]=sum/Ai[i];
}
for(size_t i=0; i < n; ++i)
(*x)[i]=B[i];
delete[] index;
delete[] B;
delete[] A;
{Stack->push<realarray*>(x); return;}
}
// Solve the linear equation ax=b by LU decomposition, returning the
// solution x, where a is an n x n matrix and b is an n x m matrix.
// If no solution exists, return an empty array.
#line 1301 "./runarray.in"
// realarray2* solve(realarray2 *a, realarray2 *b, bool warn=true);
void gen_runarray50(stack *Stack)
{
bool warn=vm::pop<bool>(Stack,true);
realarray2 * b=vm::pop<realarray2 *>(Stack);
realarray2 * a=vm::pop<realarray2 *>(Stack);
#line 1302 "./runarray.in"
size_t n=checkArray(a);
for(size_t i=0; i < n; ++i) {
real *Ai=A+i*n;
real *Bi=B+i*m;
real *Bip=B+index[i]*m;
for(size_t k=0; k < m; ++k) {
real sum=Bip[k];
Bip[k]=Bi[k];
size_t jk=k;
for(size_t j=0; j < i; ++j, jk += m)
sum -= Ai[j]*B[jk];
Bi[k]=sum;
}
}
for(size_t i=n; i > 0;) {
--i;
real *Ai=A+i*n;
real *Bi=B+i*m;
for(size_t k=0; k < m; ++k) {
real sum=Bi[k];
size_t jk=(i+1)*m+k;
for(size_t j=i+1; j < n; ++j, jk += m)
sum -= Ai[j]*B[jk];
Bi[k]=sum/Ai[i];
}
}
for(size_t i=0; i < n; ++i) {
real *Bi=B+i*m;
array *xi=new array(m);
(*x)[i]=xi;
for(size_t j=0; j < m; ++j)
(*xi)[j]=Bi[j];
}
delete[] index;
delete[] B;
delete[] A;
{Stack->push<realarray2*>(x); return;}
}
// Compute the determinant of an n x n matrix.
#line 1364 "./runarray.in"
// real determinant(realarray2 *a);
void gen_runarray51(stack *Stack)
{
realarray2 * a=vm::pop<realarray2 *>(Stack);
#line 1365 "./runarray.in"
real *A;
copyArray2C(A,a);
size_t n=checkArray(a);
real det=LUdecompose(A,n,NULL,false);
size_t n1=n+1;
for(size_t i=0; i < n; ++i)
det *= A[i*n1];
real *gamma=new real[n-2];
real *delta=new real[n-2];
gamma[0]=read<real>(c,0)*binv;
delta[0]=read<real>(a,0)*binv;
u[0]=read<real>(f,0)*binv;
real beta=read<real>(c,n-1);
real fn=read<real>(f,n-1)-beta*read<real>(u,0);
real alpha=read<real>(b,n-1)-beta*delta[0];
// Find a root for the specified continuous (but not necessarily
// differentiable) function. Whatever value t is returned, it is guaranteed
// that t is within [a, b] and within tolerance of a sign change.
// An error is thrown if fa and fb are both positive or both negative.
//
// In this implementation, the binary search is interleaved
// with a modified version of quadratic interpolation.
// This is a C++ port of the Asymptote routine written by Charles Staats III.
#line 1739 "./runarray.in"
// real _findroot(callableReal *f, real a, real b, real tolerance, real fa, real fb);
void gen_runarray65(stack *Stack)
{
real fb=vm::pop<real>(Stack);
real fa=vm::pop<real>(Stack);
real tolerance=vm::pop<real>(Stack);
real b=vm::pop<real>(Stack);
real a=vm::pop<real>(Stack);
callableReal * f=vm::pop<callableReal *>(Stack);
#line 1741 "./runarray.in"
if(fa == 0.0) {Stack->push<real>(a); return;}
if(fb == 0.0) {Stack->push<real>(b); return;}
const char* oppsign="fa and fb must have opposite signs";
int sign;
// If halving the interval already puts us within tolerance,
// don't bother with the interpolation step.
if(b-a >= twicetolerance) {
real factor=1.0/(b-a);
real q_A=2.0*(fa-2.0*ft+fb)*factor*factor;
real q_B=(fb-fa)*factor;
quadraticroots Q=quadraticroots(q_A,q_B,ft);
// If the interpolation somehow failed, continue on to the next binary
// search step. This may or may not be possible, depending on what
// theoretical guarantees are provided by the quadraticroots function.
real root;
bool found=Q.roots > 0;
if(found) {
root=t+Q.t1;
if(root <= a || root >= b) {
if(Q.roots == 1) found=false;
else {
root=t+Q.t2;
if(root <= a || root >= b) found=false;
}
}
}
// If the interpolated value is close to one edge of
// the interval, move it farther away from the edge in
// an effort to catch the root in the middle.
real margin=(b-a)*1.0e-3;
if(t-a < margin) t=a+2.0*(t-a);
else if(b-t < margin) t=b-2.0*(b-t);
#line 1833 "./runarray.in"
// real simpson(callableReal *f, real a, real b, real acc=DBL_EPSILON, real dxmax=0);
void gen_runarray66(stack *Stack)
{
real dxmax=vm::pop<real>(Stack,0);
real acc=vm::pop<real>(Stack,DBL_EPSILON);
real b=vm::pop<real>(Stack);
real a=vm::pop<real>(Stack);
callableReal * f=vm::pop<callableReal *>(Stack);
#line 1835 "./runarray.in"
real integral;
if(dxmax <= 0) dxmax=fabs(b-a);
callable *oldFunc=Func;
Func=f;
FuncStack=Stack;
if(!simpson(integral,wrapFunction,a,b,acc,dxmax))
error("nesting capacity exceeded in simpson");
Func=oldFunc;
{Stack->push<real>(integral); return;}
}
// Compute the fast Fourier transform of a pair array
#line 1848 "./runarray.in"
// pairarray* fft(pairarray *a, Int sign=1);
void gen_runarray67(stack *Stack)
{
Int sign=vm::pop<Int>(Stack,1);
pairarray * a=vm::pop<pairarray *>(Stack);
#line 1849 "./runarray.in"
#ifdef HAVE_LIBFFTW3
unsigned n=(unsigned) checkArray(a);
array *c=new array(n);
if(n) {
Complex *f=utils::ComplexAlign(n);
fftwpp::fft1d Forward(n,intcast(sign),f);