Wednesday, March 11, 2015

Finding all the integers [1,10,000,000] that can't be represented by a sum of 1,2,3,4 tetrahedrals in Java

Time complexity of the method main method is less than O(n2) and space complexity is O(n).

Initializing:


List tetraNumb = th.computeTetrahedralNumbers(limit);

Collections.sort(tetraNumb);

List tetraNumbPair = th.computeTetrahedralNumberPairs(tetraNumb, limit);

Collections.sort(tetraNumbPair);

List result = execute(tetraNumList, tetraNumPairList, limit);


Computing all the tetrahedral numbers that are smaller than the given threshold:


public List computeTetrahedralNumbers(double limit){

    List tetraNumList = new ArrayList();

    int i = 1;

    int tetra_N = 0;

    while (tetra_N <= limit){
        int tri_N = 0, n;

        tetra_N = 0;

        for (n = 1; n <= i; n++) {
            tri_N += n;

            tetra_N += tri_N;

        }

        if(tetra_N <= limit){
            tetraNumList.add(tetra_N);

        }

        i++;

    }

    return tetraNumList;

}


Creating a list cthat contains the sum of tetrahedral pairs smaller than a threshold:


/**

* Creates the list that contains the sum of tetrahedral pairs smaller than the limit.

* To do so,it checks the pairs between each number and the rest(including itself) until

* the pair's summation is larger than the limit,in which case the iteration

* continues with the next tetrahedral which is paired at most till the position

* the previous check stopped.

* The space complexity is O(n^(2/3)) and the time complexity is O(n^2)

@param tetraNumList all the tetrahedral numbers smaller than the limit,sorted

@param limit the tetrahedral threshold

@return unsorted list of tetrahedral pairs

*/


public List computeTetrahedralNumberPairs(List tetraNumList, double limit) {

    List pairs = new ArrayList<>();

    int max = tetraNumList.size();

    int i, j;

    int sum;

for (i = 0; i < tetraNumList.size(); i++) {//cost: O(n^1/3)

for (j = 0; j < max; j++) {//worst case cost: O(n^1/3)

    sum = tetraNumList.get(i) + tetraNumList.get(j);

    if (sum < limit) {
        if (!pairs.contains(sum)) {

            pairs.add(sum);

        }

    } else {



// there is no need to continue since the array is sorted so

// all the following summations will be larger than the limit

// and also the next loop doesn't have to check beyond this

// index, making the time complexity definitely smaller than

// n*n



        max = j;

        break;

    }

}

}

return pairs;

}


The main method (execute) :


/**

* For each integer i bigger/equal than 1 and smaller/equal than the upper

* limit checks if i is:

*      -tetrahedral (cost O(logn))

*      -summed pair of tetrahedrals (cost O(logn))

*      -summed triplet of tetrahedrals (cost O((n^1/3)logn))

*      -summed quartet of tetrahedrals (cost O((n^2/3)logn))

* If all these condition are false,the number is part of the final result

*/


public List execute(List tetraNumb, List tetraNumbPair, int limit) {

    List nonTetra = new ArrayList<>();

    for (int i = 1; i <= limit; i++) { 
        if(Collections.binarySearch(tetraNumb, i) >= 0){

            continue;

        }

        if(Collections.binarySearch(tetraNumbPair, i) >= 0){

            continue;

        }

        if(searchOnTripletTetrahedrals(tetraNumb, tetraNumbPair, i) >= 0){

            continue;

        }

        if(searchOnQuartetTetrahedrals(tetraNumbPair, i) >= 0){

            continue;

        }

        nonTetra.add(i);

    }

    return nonTetra;

}


Searching on triplet and quartet tetrahedrals:


/**

* For each integer i bigger/equal than 1 and smaller/equal than the upper

* limit checks if i is:

*      -tetrahedral (cost O(logn))

*      -summed pair of tetrahedrals (cost O(logn))

*      -summed triplet of tetrahedrals (cost O((n^1/3)logn))

*      -summed quartet of tetrahedrals (cost O((n^2/3)logn))

* If all these condition are false,the number is part of the final result

*/


public List execute(List tetraNumb, List tetraNumbPair, int limit) {

    List nonTetra = new ArrayList<>();

    for (int i = 1; i <= limit; i++) { 
        if(Collections.binarySearch(tetraNumb, i) >= 0){

            continue;

        }

        if(Collections.binarySearch(tetraNumbPair, i) >= 0){

            continue;

        }

        if(searchOnTripletTetrahedrals(tetraNumb, tetraNumbPair, i) >= 0){

            continue;

        }

        if(searchOnQuartetTetrahedrals(tetraNumbPair, i) >= 0){

            continue;

        }

        nonTetra.add(i);

    }

    return nonTetra;

}





/**

* For each tetrahedral number (tn),smaller than the target, attempts to find,using

* binary search on tetraNumPairList, a number tp=target-tn which is a triplet of

* tetrahedral sum.

* Space complexity is insignificant and time complexity is O((n^1/3)logn) since

* the number of tetrahedral numbers is O(n^1/3) and the cost of binary search is O(logn)

@param tetraNumList the sorted list of tetrahedrals

@param tetraNumPairList the sorted list of summed pairs of tetrahedrals

@param num the target number for which the method is called

@return positive if found, negative if not

*/


public int searchOnTripletTetrahedrals(List tetraNumList, List tetraNumPairList, int num) {

    int i, found, searchQ;

for (i = 0; i < tetraNumList.size(); i++) {//cost: O(n^1/3)

    searchQ = num - tetraNumList.get(i);

    if (searchQ > 0) {

if ((found = Collections.binarySearch(tetraNumPairList, searchQ)) >= 0) {//cost:O(log(n^2/3))

    return found;

}

else {



// since the array is sorted and the tetrahedral numbers are positive

// it is impossible to find a solution after this index



    return -1;

}

}

return -1;

}





/**

* For each summed pair of tetrahedrals tp1,smaller than the target,attempts to

* find,using binary search on tetraNumPairList, a quartet  of tetrahedral sum

* tp2=target-tp1.

* Space complexity is insignificant and time complexity is O((n^2/3)logn) since

* the number of summed pairs of tetrahedral numbers is O(n^2/3) and the cost

* of binary search is O(logn)

@param tetraNumPairList the sorted list of summed pairs of tetrahedrals

@param num the target number for which the method is called

@return positive if found, negative if not

*/


public int searchOnQuartetTetrahedrals(List tetraNumPairList, int num) {

    int i, found, searchQ;

for (i = 0; i < tetraNumPairList.size(); i++) {//cost: O(n^2/3)

    searchQ = num - tetraNumPairList.get(i);

    if (searchQ > 0) {

if ((found = Collections.binarySearch(tetraNumPairList, searchQ)) >= 0) {//cost:O(log(n^2/3))

    return found;

}

else {



// since the array is sorted and the tetrahedral numbers are positive

// it is impossible to find a solution after this index



    return -1;

}

}

return -1;

}

Calculating the number of tetrahedrals required to represent an integer in Java using dynamic programming

Computing all the tetrahedral numbers that are smaller than the given threshold:


public static Integer[] computeTetrahedralNumbers(double limit){

    List tetraNumList = new ArrayList();

    int i = 1;

    int tetra_N = 0;

    while (tetra_N <= limit){
        int tri_N = 0, n;

        tetra_N = 0;

        for (n = 1; n <= i; n++) {
            tri_N += n;

            tetra_N += tri_N;

        }

        if(tetra_N <= limit){
            tetraNumList.add(tetra_N);

        }

        i++;

    }

    return tetraNumList.toArray(new Integer[tetraNumList.size()]);

}


Initializing the arrays:


Integer[] tetrahedrals = computeTetrahedralNumbers(n);

/**

* Each cell C[i,j] equals to the number of tetrahedrals required to represent

* the integer j,taking into consideration the tetrahedrals from the

* first till the i-th.

*/


C = new int[tetrahedrals.length][n+1];

for(int i = 0; i    C[i][0] = 0;

}

/**

* Each cell of the first row is initialized with the value of its

* column since 1 is a tetrahedral and so each integer can be

* represented by a sum of ones.

*/


for (int j = 1; j < n+1; j++) {
    C[0][j]=j;

}


Calculating the number of tetrahedrals required to represent an integer:


/**

* Utilizes the array C from the first column till the n-th.

* Each utilized cell is either assigned the value of the cell above it (when

* the integer it represents is smaller than the maximum tetrahedral that can

* be used-since that tetrahedral obviously cant be taken into consideration

* because the result would be bigger than the target) or the minimum value

* between the cell above it and the number of tetrahedrals required to

* represent the integer n-(maximum allowed tetrahedral) plus one (so the maximum

* allowed tetrahedral is taken into consideration).

*

* When the method is finished,the first n+1 cells of the last row contain

* the minimum number of tetrahedrals required to represent the integers from 0 to n

* and the first n+1 columns contain the process done for that calculation.

*

* If n=number of tetrahedrals smaller than the limit and W=number of integers

* the time and space complexity is pseudo-polynomial-O(nW).The number of integers

* (10000) can be represented with 14 bits and if it gets doubled,15 bits will be

* needed whereas the number of operations will be at least doubled(since an

* increase at the number of integers also increases the available tetrahedrals)

* so when the input is increased by one bit,the complexity is exponential

* if the input is seen as bits and pseudo-polynomial if seen as number.If

* the number of tetrahedrals is doubled,the array will have doubled amount of

* rows(double the space) and the number of operations will be doubled too,

* so complexity will be considered polynomial.

*

*

@param n

@return the number of tetrahedrals required to represent n

*/




public int computeTetrahedralSumCount(int n) {

    for (int i = 1; i < C.length; i++) {
        for (int j = 1; j <= n; j++) {
//could be avoided under the

//assumption that the method has been called for all the integers

//before the n-th and the array is already correct till the n-th

//column and set j=n without looping

            if(j                C[i][j]=C[i-1][j];

            }else{

                C[i][j]=Math.min(C[i-1][j], 1+C[i][j-tetrahedrals[i]]);

            }

        }

    }

    return C[C.length-1][n];

}

Monday, March 9, 2015

Definite integrals calculation in Java

IntegralApproximations.java

A class containing methods to calculate definite integrals and error margins.

Supports:


Example: Calculating the integral of sine in [0,pi/2] using 2 strips.

int n = 2;

double[] x = new double[n + 1];

double[] y = new double[n + 1];

x[0] = 0.28559933214452704;

x[1] = 0.8567979964335803;

x[2] = 1.4279966607226338;

for (int i = 0; i < n + 1; i++) {

    y[i] = (double) Math.round(Math.sin(x[i]) * 1000000) / 1000000;

}

System.out.println("Trapezoidal approximation : " + trapezoidal(x, y));

System.out.println("Simpson approximation     : " + simpson(x, y));

Calculating the error

double e1, e2;

double[] xe = new double[199];

double[] ye = new double[199];

double start = 0;

double dif = x[0] / 198;

for (int i = 0; i < 199; i++) {

    xe[i] = start;

    start += dif;

    ye[i] = Math.sin(xe[i]);

}

e1 = simpson(xe, ye) + simpError(x[0], 198, Math.sin(x[0]));

start = x[2];

dif = ((Math.PI / 2) - x[2]) / 198;

for (int i = 0; i < 199; i++) {

    xe[i] = start;

    start += dif;

    ye[i] = Math.sin(xe[i]);

}

e2 = simpson(xe, ye) + simpError(Math.PI / 2 - x[2], 198, 1);

System.out.println("Maximum theoretical error (trapezoidal) : " + (e1 + e2 + trapError(x[2] - x[0], n, Math.sin(x[2]))));

System.out.println("Actual error (trapezoidal) : " + (1 - trapezoidal(x, y)));

System.out.println("Maximum theoretical error (simpson)     : " + (e1 + e2 + simpError(x[2] - x[0], n, Math.sin(x[2]))));

System.out.println("Actual error (simpson)     : " + (1 - simpson(x, y)));

Output

Trapezoidal approximation : 0.7948383637221537

Simpson approximation     : 0.8176811695057372

Maximum theoretical error (trapezoidal) : 0.21356634499073798

Actual error (trapezoidal) : 0.20516163627784634

Maximum theoretical error (simpson)     : 0.18349059382360064

Actual error (simpson)     : 0.18231883049426278

Simpson's rule in Java

Wikipedia

Calculating the integral:


/**

*
@param x ascending order,odd number of points
@param y
@return
*/

static public double simpson(double[] x, double[] y) {
    double s1 = 0, s2 = 0;
    double dif = x[x.length - 1] - x[0];
    int n = x.length - 1;
    if (n % 2 != 0) {
        throw new IllegalArgumentException();
    }
    for (int i = 1; i <= (n * 0.5) - 1; i++) {
        s1 += y[2 * i];
    }
    s1 *= 2;
    for (int i = 1; i <= n * 0.5; i++) {
        s2 += y[(2 * i) - 1];
    }
    s2 *= 4;
    return ((dif / (3 * n)) * (y[0] + y[n] + s1 + s2));

}

Calculating the maximum theoretical error:


/**

*
@param dif total length of the strips
@param n number of strips
@param max max value of the 4nd derivative
@return
*/

static public double simpError(double dif, int n, double max) {
    return ((Math.pow(dif, 5) / (180 * n * n * n * n)) * max);
}

This is part of the Definite Integral Approximations project.

Trapezoidal rule in Java

Wikipedia

Calculating the integral:


/**

*

* @param x ascending order

* @param y

* @return

*/

static public double trapezoidal(double[] x, double[] y) {

    double s = 0;

    double dif = x[x.length - 1] - x[0];

    int n = x.length - 1;

    for (int i = 1; i <= n - 1; i++) {

        s += y[i];

    }

    s *= 2;

    return (dif / (2 * n)) * (y[0] + y[n] + s);

}

Calculating the maximum theoretical error:


/**

*

* @param dif total length of the strips

* @param n number of strips

* @param max max value of the 2nd derivative

* @return

*/

static public double trapError(double dif, int n, double max) {

    return ((Math.pow(dif, 3) / (12 * n * n)) * max);

}

This is part of the Definite Integral Approximations project.

Sunday, March 8, 2015

Function Approximations in Java

FunctionApproximations.java

A class containing methods to calculate the coefficients and values based on a set of initial values.

Supports:


Example: Approximating sine values based on 12 initial points.


int n = 11;

double[] stx = new double[n + 1];

double[] y = new double[n + 1];

double dif = (Math.PI * 2) / (n);

double start = -Math.PI;

for (int i = 0; i < n + 1; i++) {

    stx[i] = start;

    start += dif;

    y[i] = (double) Math.round(Math.sin(stx[i]) * 100000) / 100000;

}

double[] newtonPolCoef = FunctionApproximations.newtonPolCoef(stx, y);

double[] splineCoef = FunctionApproximations.splineCoef(stx, y, 3);

double[] lsCoef = FunctionApproximations.leastSqCoeff(stx, y, 5);

Random random=new Random();

double val,correct,newton,spline,leastsq;

for (int i = 0; i < 10; i++) {

    val=random.nextDouble();

    correct=Math.sin(val);

    newton=FunctionApproximations.newtonPolVal(newtonPolCoef, stx, getX(val));

    spline=FunctionApproximations.splineVal(splineCoef, stx, getX(val));

    leastsq=FunctionApproximations.leastSqVal(lsCoef, getX(val));

    System.out.println("sin("+val+")");

    System.out.println("Newton approximation :     "+newton+"    off by   "+(correct-newton));

    System.out.println("Cubic splines :            "+spline+"    off by   "+(correct-spline));

    System.out.println("Least squares 5th degree : " +leastsq+"    off by   "+(correct-leastsq));

    System.out.println("----");

}

static private double getX(double x) {

    if (Math.abs(x) <= Math.abs(Math.PI)) {

        return x;

    } else {

        if (x > 0) {

            x -= Math.round(x / (2 * Math.PI)) * (2 * Math.PI);


        } else {

            x += Math.round(Math.abs(x) / (2 * Math.PI)) * (2 * Math.PI);

        }

        return x;

    }

}

Sample output:

sin(0.8481863801681208)
Newton approximation :     0.7500825572784057    off by   -3.455657819895208E-7
Cubic splines :            0.7500853256850928    off by   -3.113972469104276E-6
Least squares 5th degree : 0.7446845168230829    off by   0.005397694889540783
----
sin(0.17370422573181987)
Newton approximation :     0.1728302183995918    off by   1.7900743105314643E-6
Cubic splines :            0.17285859735632642    off by   -2.6588882424072313E-5
Least squares 5th degree : 0.1704451410039368    off by   0.0023868674699655534
----
sin(0.9222664997998143)
Newton approximation :     0.7969736441928723    off by   -9.775787263022195E-7
Cubic splines :            0.7969127151051372    off by   5.995150900883761E-5
Least squares 5th degree : 0.7921460535443667    off by   0.004826613069779273
----
sin(0.42918641383160216)
Newton approximation :     0.4161283242433726    off by   2.818337875132304E-6
Cubic splines :            0.41601147561349894    off by   1.1966696774878827E-4
Least squares 5th degree : 0.4110357193164086    off by   0.005095423264839138
----
sin(0.5240316104273179)
Newton approximation :     0.5003722902694624    off by   2.5088399099315595E-6
Cubic splines :            0.5002095950629291    off by   1.6520404644326803E-4
Least squares 5th degree : 0.4946962081563806    off by   0.0056785909529917244
----
sin(0.9800507235185272)
Newton approximation :     0.8305269746540256    off by   -1.3510869794064462E-6
Cubic splines :            0.8303843741206196    off by   1.4124944642657233E-4
Least squares 5th degree : 0.8262637304226693    off by   0.00426189314437686
----
sin(0.9303877316203922)
Newton approximation :     0.8018527171875109    off by   -1.0374269545643244E-6
Cubic splines :            0.8017809837980641    off by   7.069596249231758E-5
Least squares 5th degree : 0.7970983401665966    off by   0.004753339593959738
----
sin(0.6236951478334793)
Newton approximation :     0.5840367621157957    off by   1.826036797991648E-6
Cubic splines :            0.5838957413617496    off by   1.428467908440867E-4
Least squares 5th degree : 0.5780582273554796    off by   0.005980360797114059
----
sin(0.5844538429625159)
Newton approximation :     0.5517418299721984    off by   2.1323006360596253E-6
Cubic splines :            0.5515834663608791    off by   1.6049591195543833E-4
Least squares 5th degree : 0.5458425471133572    off by   0.005901415159477286
----
sin(0.37727308863399756)
Newton approximation :     0.36838388119885634    off by   2.8261127495432525E-6
Cubic splines :            0.36831036229846276    off by   7.634501314313091E-5
Least squares 5th degree : 0.36372091601169265    off by   0.004665791299913236
----

Least squares method in Java

Wikipedia

Calculating the coefficients:

static public double[] leastSqCoeff(double[] x, double[] y, int degree) {

    if (degree < 0) {
        throw new IllegalArgumentException();
    }
    ++degree;
    int n = x.length;
    double[][] a = new double[n][degree];
    double[] b = new double[degree];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < degree; j++) {
            a[i][j] = Math.pow(x[i], j);
        }
    }
    double[][] ata = new double[degree][degree];
    for (int i = 0; i < degree; i++) {
        for (int j = 0; j < degree; j++) {
            ata[i][j] = MatricesBasic.vectorM(MatricesBasic.getColumn(a, i), MatricesBasic.getColumn(a, j));
        }
        b[i] = MatricesBasic.vectorM(MatricesBasic.getColumn(a, i), y);
    }
    b = Matrices.gauss(ata, b);
    return b;

}

Approximating the value based on the coefficients:

static public double leastSqVal(double[] coef, double val) {

    double res = 0;
    for (int i = 0; i < coef.length; i++) {
        res += coef[i] * Math.pow(val, i);
    }
    return res;
}

This is part of the Function Approximations project.

Creating order 2 and 3 splines in Java

Wikipedia

Calculating the coefficients:

static public double[] splineCoef(double[] x, double[] y, int degree) {

    if (degree != 2 && degree != 3) {
        throw new IllegalArgumentException();
    }
    int n = (x.length - 1) * (degree + 1);
    double[][] a = new double[n][n];
    double[] b = new double[n];
    double[] coef;
//s
    int k = 0;
    for (int i = 0; i < (x.length - 1) * 2; i += 2, k++) {
        for (int j = 0; j < degree + 1; j++) {
            for (int l = 0; l < 2; l++) {
                a[i + l][j + ((i / 2) * (degree + 1))] = Math.pow(x[k + l], degree - j);
            }
        }
        for (int l = 0; l < 2; l++) {
            b[i + l] = y[k + l];
        }
    }
//s'
    int line = (x.length - 1) * 2;
    int column = 0;
    for (int i = 1; i < x.length - 1; i++) {
        for (int j = 0; j < degree; j++) {
            a[line + i - 1][column + j] = (degree - j) * Math.pow(x[i], degree - 1 - j);
            a[line + i - 1][(column + j) + degree + 1] = -a[line + i - 1][column + j];
        }
        column += degree + 1;
    }
//s"
    if (degree > 2) {
        line += x.length - 2;
        column = 0;
        for (int i = 1; i < x.length - 1; i++) {
            for (int j = 0; j < degree - 1; j++) {
                a[line + i - 1][column + j] = ((degree - j) * (degree - 1 - j)) * Math.pow(x[i], degree - 2 - j);
                a[line + i - 1][(column + j) + degree + 1] = -a[line + i - 1][column + j];
            }
            column += degree + 1;
        }
        if (degree == 3) {
            a[n - 2][0] = 6 * x[0];
            a[n - 2][1] = 2;
            a[n - 1][n - 4] = 6 * x[x.length - 1];
            a[n - 1][n - 3] = 2;
        }

    } else {
        a[n - 1][0] = 1;
    }
    Jama.Matrix A = new Jama.Matrix(a);
    Jama.Matrix c = new Jama.Matrix(b, n);
    Jama.Matrix sol = A.solve(c);
    coef = sol.getColumnPackedCopy();
    return coef;
}

Approximating the value based on the coefficients:

static public double splineVal(double[] coef, double[] x, double val) {

    if (val < x[0]) {
        return Double.NaN;
    }
    int degree = coef.length / x.length;
    for (int i = 1; i < x.length; i++) {
        if (val <= x[i]) {
            int indx = (i - 1) * (degree + 1);
            double s = 0;
            for (int j = 0; j < degree + 1; j++) {
                s += coef[indx + j] * Math.pow(val, degree - j);
            }
            return s;
        }
    }
    return Double.NaN;
}

This is part of the Function Approximations project.

Newton polynomial calculation in Java

Wikipedia

Calculating the coefficients:

static public double[] newtonPolCoef(double[] x, double[] y) {

    int n = x.length - 1;
    double dd[][] = new double[n][];
    double[] a = new double[n + 1];
    for (int i = 0; i < n; i++) {
        dd[i] = new double[n - i];
    }
    for (int j = 0; j < n; j++) {
        dd[0][j] = (y[j + 1] - y[j]) / (x[j + 1] - x[j]);
    }
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < n - i; j++) {
            dd[i][j] = (dd[i - 1][j + 1] - dd[i - 1][j]) / (x[j + i + 1] - x[j]);
        }
    }
    a[0] = y[0];
    for (int i = 1; i < n + 1; i++) {
        a[i] = dd[i - 1][0];
    }
    return a;
}

Approximating the value based on the coefficients:

static public double newtonPolVal(double[] coef, double[] x, double val) {

    double r = coef[0];
    double mul = 1;
    for (int i = 1; i < x.length; i++) {
        mul *= (val - x[i - 1]);
        r += coef[i] * mul;
    }
    return r;
}

This is part of the Function Approximations project.

Saturday, March 7, 2015

Linux shell implementation.

Source Code

A fairly simple implementation of a Linux shell in C++(don't expect anything clever on the code,I'm quite rusty in C++).

Allows directory change,execution of commands and pipeline(2 commands), redirection of input/output and background execution.The symbols used are the common ones(cd,|,>,>>,<,&).

Round Robin algorithm is used to handle the background processes.

Supported commands examples:
  • cd "new/dir/" to change directory.
  • "command"
  • "command&"
  • "dir/to/command/command"
  • "command1 | command2"
  • "command1 | command2&"
  • "command1file"
  • "command>>file"
  • "command>file"
  • "command<file"
  • "exit"

Handling input-output redirection for Linux commands in C++

Opening the file and duplicating the file descriptor for input.

Throws errno if either of those operations failed.
Retuns the file descriptor.
int startRedirectIn(const char *file){
  int in;
  in=open(file,O_RDONLY);
  if(in<0){
    throw errno;
  }
  int dup=dup2(in,0);
  if(dup<0){
    close(in);
    throw errno;
  }
  return in;
}

Opening/creating the file and duplicating the file descriptor for output.

Throws errno if either of those operations failed.
append is used to distinguish between ">" and ">>"
Retuns the file descriptor.

int startRedirectOut(const char *file,bool append){
  int out;
  if(append){
    out=open(file,O_WRONLY | O_CREAT | O_APPEND);
  }else{
    out=open(file,O_WRONLY | O_CREAT);
  }
  if(out<0){
    throw errno;
  }
  int dup=dup2(out,1);
  if(dup<0){
    close(out);
    throw errno;
  }
  return out;
}

Closing a file descriptor/stopping the redirection.

void stopRedirect(int rdr){
  if(rdr!=-1){
    close(rdr);
  }
}


This is part of the LinuxShell project.

Implementing a pipeline for two commands in Linux from C++

Executes the first command and redirects it's output to the second.

False waitExecution causes the the first command to be executed at the time of the call and the second when the background handler allows it.
redIn refers to the first command and redOut to the second.

If the command parameters do not contain "/" the executable is searched in PATH.

Throws errno in case of failed pipelining,failed forking,failed redirection when waitExecution is true and failed background handling and initiation of the new process.

redIn,redOut should be NULL if no redirection is required,append should be true if output needs to be redirected to a file,appened at the end.

Check LinuxShell for missing methods and complete source code.

void pipe(const char *command1, char *const args1[],const char *command2, char *const args2[],bool waitExecution,const char *redIn,const char* redOut,bool append){

  int pipeDesc[2];
  bool error=false;
  if(pipe(pipeDesc)<0){
    throw errno;
  }
  pid_t pid1,pid2;
  int in=-1,out=-1;
  if((pid1=fork())==0){//first command handling
    dup2(pipeDesc[1],1);
    close(pipeDesc[0]);
    close(pipeDesc[1]);
    if(redIn!=NULL){
      try{
        in=startRedirectIn(redIn);
      }catch(int ex){
        exit(ex);
      }
    }
    stopRedirect(in);
    execvp(command1,args1);
    exit(1);
  }
  if(pid1==-1){//fork error
    throw errno;
  }
  if((pid2=fork())==0){//second command handling
    dup2(pipeDesc[0],0);
    close(pipeDesc[0]);
    close(pipeDesc[1]);
    if(redOut!=NULL){
      try{
        in=startRedirectOut(redOut,append);
      }catch(int ex){
        exit(ex);
      }
    }
    stopRedirect(out);
    execvp(command2,args2);
    exit(1);
  }
  if(pid2==-1){//fork error
    throw errno;
  }
  close(pipeDesc[0]);
  close(pipeDesc[1]);

  if(waitExecution){
    int status;
    pid_t ws=wait(&status);
    if(ws!=-1){//first command is executed
      if(WIFEXITED(status)){
        int exitStatus=WEXITSTATUS(status);
        if(exitStatus!=0){
          kill(pid2,SIGKILL);
          throw exitStatus;
        }
      }
    }else{// error while executing the first command
      throw errno;
    }
    ws=wait(&status);
    if(ws!=-1){//second command is executed
      if(WIFEXITED(status)){
        int exitStatus=WEXITSTATUS(status);
        if(exitStatus!=0){
          throw exitStatus;
        }
      }
    }else{// error while executing the second command
      throw errno;
    }
  }else{// waitExecution is false
    int status;
    pid_t ws=wait(&status);
    bool pid1Finished=true;
    if(ws!=-1){//first command is executed
      if(WIFEXITED(status)){
        int exitStatus=WEXITSTATUS(status);
        if(exitStatus!=0){
          kill(pid2,SIGKILL);
          throw exitStatus;
        }
      }
    }else{// error while executing the first command
      throw errno;
    }
    if(kill(pid2,SIGSTOP)==0){
      backgroundProcs.push_back(pid2);
    }else{
      throw errno;
    }
  }


}