<commit_before>/*
 * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
 * Applied Mathematics, Norway.
 *
 * Contact information: E-mail: tor.dokken@sintef.no
 * SINTEF ICT, Department of Applied Mathematics,
 * P.O. Box 124 Blindern,
 * 0314 Oslo, Norway.
 *
 * This file is part of GoTools.
 *
 * GoTools is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * GoTools 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with GoTools. If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public
 * License, a covered work must retain the producer line in every data
 * file that is created or manipulated using GoTools.
 *
 * Other Usage
 * You can be released from the requirements of the license by purchasing
 * a commercial license. Buying such a license is mandatory as soon as you
 * develop commercial activities involving the GoTools library without
 * disclosing the source code of your own applications.
 *
 * This file may be used in accordance with the terms contained in a
 * written agreement between you and SINTEF ICT.
 */

#define BOOST_TEST_MODULE compositemodel/offsetSurfaceSetTest
#include <boost/test/included/unit_test.hpp>

#include "GoTools/compositemodel/OffsetSurfaceUtils.h"
#include "GoTools/utils/errormacros.h"
#include "GoTools/geometry/Utils.h"
#include "GoTools/geometry/ObjectHeader.h"
#include "GoTools/geometry/BoundedSurface.h"
#include "GoTools/geometry/GoTools.h"

#include <fstream>
#include <math.h>
#include <vector>
#include <string>

using namespace Go;
using std::vector;
using std::string;
using std::ifstream;

// #define TEST_NEW_CASES

// #define TEST_UNSUPPORTED_CASES

// #define TEST_FAILING_CASES

#define TEST_WORKING_CASES

struct Config {
public:
    Config()
        : output_filename("tmp/offsetSurfaceSetTest_result.g2")

    {

        const std::string data_basedir("../../gotools-private-data/compositemodel/Offset");

#ifdef GOTOOLS_TEST_PRIVATE_DATA

        // NEW CASES!!!
#ifdef TEST_NEW_CASES

#endif

        // CASES NOT SUPPORTED (EARLY EXIT WITH ERROR MESSAGE)!!!
#ifdef TEST_UNSUPPORTED_CASES

        // Degenerate patch (triangle): Ok w/ offset=1e-02,eps=1e-03. Using 0.01*epsgeo as curvature_tol.
        // Contains kink curve which is not an iso curve. Exits with failure.
        filenames.push_back(data_basedir+"/fanta_ro2_sub2b.g2");
        offset.push_back(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-03);//6;

        // Tricky case with a degenerate surface. The degenerate point is not well defined with the
        // normal varying as the evaluation approaches from different iso lines. Will require extensive
        // smoothing. Currently not handled using SplineSurface (equation system too large). We need
        // LRSplineSurface (and even with that the task may be to tricky). Exits with failure.
        filenames.push_back(data_basedir+"/fanta_ro2_sub.g2");
        offset.push_back(0.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;
#endif

        // FAILING CASES!!!
#ifdef TEST_FAILING_CASES
        // Added 2017-10-09. Crash 3. Tricky case with a degenerate underlying surface, with a trimmed
        // boundary meeting in a degenerate corner (parallell tangents).
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_BoundedSurf__20170929-115934.549.g2");
        offset.push_back(1.0e-03);
        epsgeo.push_back(1.0e-04);
#endif

        // WORKING CASES!!!
#ifdef TEST_WORKING_CASES

        // Added 2017-10-09. Crash 2.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf_OffsetTest_20170929-110347.373_406_434.g2");
        offset.push_back(1.0e-03);
        epsgeo.push_back(1.0e-04); // Initially given epsgeo = 1.0e-03, conflicts with topology (too many twin edges).

        // Added 2017-10-09. Crash 1.
        filenames.push_back(data_basedir+"/TopSolid/Source-TopSolid_SplineSurf_OffsetTest_20170929-103855.922_949.g2");
        offset.push_back(1.0e-03);
        epsgeo.push_back(1.0e-04); // Initially given epsgeo = 1.0e-03, conflicts with topology (too many twin edges).

        filenames.push_back(data_basedir+"/TopSolid/TopSolid_BoundedSurf__20170623-173106.658.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // Added 2017-06-23
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170623-173106.544.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // Added 2017-06-23
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170623-173916.090.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // Added 2017-06-23
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170623-175900.205.g2");
//      filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170627-130342.267.g2"); The same set.
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // 2 bilinear quadrats with z = 0.018.
        // Tricky case which required us to to define a transition zone.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_Surf__20170313-174324.189_221.g2");
        offset.push_back(0.1);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-05);//3);//6;

        // 4 planes meeting in kinks along linear segments.
        // Tricky case which required us to to define a transition zone.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170504-1332_kinks.g2");
        offset.push_back(3.0e-03);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-05);//3);//6;

        // A single surface with a bump in the interior. Use a negative offset value to create a self
        // intersection in the bump. Easy when using a positive offset dist, tricky when using a negative
        // offset dist. With a large offset value (< -3.0e-03) the self intersection is global.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_bump.g2");
        offset.push_back(-3.0e-03);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-05);//3);//6;

        // Self-intersections for offset dist of appr 0.3 and larger.
        filenames.push_back(data_basedir+"/test_bezier.g2");
        offset.push_back(0.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;

        // Self-int: offset=1e-02,eps=1e-03.
        // Success with removing self intersections using smoothing: offset=1e-03,eps=1e-04.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_Surf__20170404-123801.816.g2");
        offset.push_back(0.001);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;

        // Two orthogonal planes joined by a trimmed cylinder segment (w/ radius of curvature -1.38843).
        // 201706: Success after setting the twist vector to zero and reducing precond omega from 0.1 to 0.01.
        filenames.push_back(data_basedir+"/yta4.g2");
        offset.push_back(-1.5);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;

        // Illegal bounded surface, the trim loop is CW! The offset works but the offset surface is flipped.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_BoundedSurf__20170623-173916.162.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);
#endif

#endif

        GoTools::init();

    }

public:
    vector<string> filenames;
    vector<double> offset;
    vector<double> epsgeo;
    ObjectHeader header;
    const std::string output_filename;

};

BOOST_FIXTURE_TEST_CASE(offsetSurfaceSet, Config)
{
    int num_success = 0;
    int num_failures = 0;
    int num_exceptions = 0;
    for (size_t ki = 0; ki < filenames.size(); ++ki)
    {
        // Read input arguments
        std::ifstream infile(filenames[ki].c_str());
        BOOST_CHECK_MESSAGE(infile.good(), "Input file not found or file corrupt");

        vector<shared_ptr<ParamSurface> > sfs;
        while (!infile.eof())
        {
            infile >> header;
            shared_ptr<ParamSurface> sf;
            if (header.classType() == Class_SplineSurface)
            {
                sf = shared_ptr<ParamSurface>(new SplineSurface());
            }
            else if (header.classType() == Class_BoundedSurface)
            {
                sf = shared_ptr<ParamSurface>(new BoundedSurface());
            }
            else
            {
                BOOST_ERROR("Input surface type not yet supported: " << header.classType());
                continue;
            }

            sf->read(infile);

            sfs.push_back(sf);

            Utils::eatwhite(infile);
        }

        shared_ptr<SplineSurface> offset_sf;
        OffsetSurfaceStatus status;
        try
        {
            status = OffsetSurfaceUtils::offsetSurfaceSet(sfs, offset[ki], epsgeo[ki], offset_sf);
        }
        catch (...)
        {
            std::cout << "offsetSurfaceSet(): Caught exception for filename " << filenames[ki] << std::endl;
            BOOST_ERROR("Exception caught");
            ++num_exceptions;
            continue;
        }

        BOOST_CHECK_MESSAGE(status == OFFSET_OK,
                            "offsetSurfaceSet(): Failure! Returned status (!= 0): " << status);
        if (status == OFFSET_OK)
        {
            ++num_success;
            if (offset_sf.get())
            {
                std::ofstream fileout(output_filename);
                offset_sf->writeStandardHeader(fileout);
                offset_sf->write(fileout);
            }
        }
        else
        {
            ++num_failures;
        }
    }

    BOOST_TEST_MESSAGE("\nnum files: " << filenames.size() << ", num success: " << num_success << ", num failures: " <<
                  num_failures << ", num_exceptions: " << num_exceptions);

}
<commit_msg>Minor changes.<commit_after>/*
 * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
 * Applied Mathematics, Norway.
 *
 * Contact information: E-mail: tor.dokken@sintef.no
 * SINTEF ICT, Department of Applied Mathematics,
 * P.O. Box 124 Blindern,
 * 0314 Oslo, Norway.
 *
 * This file is part of GoTools.
 *
 * GoTools is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * GoTools 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with GoTools. If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public
 * License, a covered work must retain the producer line in every data
 * file that is created or manipulated using GoTools.
 *
 * Other Usage
 * You can be released from the requirements of the license by purchasing
 * a commercial license. Buying such a license is mandatory as soon as you
 * develop commercial activities involving the GoTools library without
 * disclosing the source code of your own applications.
 *
 * This file may be used in accordance with the terms contained in a
 * written agreement between you and SINTEF ICT.
 */

#define BOOST_TEST_MODULE compositemodel/offsetSurfaceSetTest
#include <boost/test/included/unit_test.hpp>

#include "GoTools/compositemodel/OffsetSurfaceUtils.h"
#include "GoTools/utils/errormacros.h"
#include "GoTools/geometry/Utils.h"
#include "GoTools/geometry/ObjectHeader.h"
#include "GoTools/geometry/BoundedSurface.h"
#include "GoTools/geometry/GoTools.h"

#include <fstream>
#include <math.h>
#include <vector>
#include <string>

using namespace Go;
using std::vector;
using std::string;
using std::ifstream;

// #define TEST_NEW_CASES

// #define TEST_UNSUPPORTED_CASES

// #define TEST_FAILING_CASES

#define TEST_WORKING_CASES

struct Config {
public:
    Config()
        : input_filename("tmp/offsetSurfaceSetTest_input.g2"),
          output_filename("tmp/offsetSurfaceSetTest_result.g2")

    {

        const std::string data_basedir("../../gotools-private-data/compositemodel/Offset");

#ifdef GOTOOLS_TEST_PRIVATE_DATA

        // NEW CASES!!!
#ifdef TEST_NEW_CASES

#endif

        // CASES NOT SUPPORTED (EARLY EXIT WITH ERROR MESSAGE)!!!
#ifdef TEST_UNSUPPORTED_CASES

        // Degenerate patch (triangle): Ok w/ offset=1e-02,eps=1e-03. Using 0.01*epsgeo as curvature_tol.
        // Contains kink curve which is not an iso curve. Exits with failure.
        filenames.push_back(data_basedir+"/fanta_ro2_sub2b.g2");
        offset.push_back(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-03);//6;

        // Tricky case with a degenerate surface. The degenerate point is not well defined with the
        // normal varying as the evaluation approaches from different iso lines. Will require extensive
        // smoothing. Currently not handled using SplineSurface (equation system too large). We need
        // LRSplineSurface (and even with that the task may be to tricky). Exits with failure.
        filenames.push_back(data_basedir+"/fanta_ro2_sub.g2");
        offset.push_back(0.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;
#endif

        // FAILING CASES!!!
#ifdef TEST_FAILING_CASES
        // Added 2017-10-09. Crash 3. Tricky case with a degenerate underlying surface, with a trimmed
        // boundary meeting in a degenerate corner (parallell tangents).
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_BoundedSurf__20170929-115934.549.g2");
        offset.push_back(1.0e-03);
        epsgeo.push_back(1.0e-04);
#endif

        // WORKING CASES!!!
#ifdef TEST_WORKING_CASES

        // Added 2017-10-09. Crash 2.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf_OffsetTest_20170929-110347.373_406_434.g2");
        offset.push_back(1.0e-03);
        epsgeo.push_back(1.0e-04); // Initially given epsgeo = 1.0e-03, conflicts with topology (too many twin edges).

        // Added 2017-10-09. Crash 1.
        filenames.push_back(data_basedir+"/TopSolid/Source-TopSolid_SplineSurf_OffsetTest_20170929-103855.922_949.g2");
        offset.push_back(1.0e-03);
        epsgeo.push_back(1.0e-04); // Initially given epsgeo = 1.0e-03, conflicts with topology (too many twin edges).

        filenames.push_back(data_basedir+"/TopSolid/TopSolid_BoundedSurf__20170623-173106.658.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // Added 2017-06-23
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170623-173106.544.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // Added 2017-06-23
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170623-173916.090.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // Added 2017-06-23
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170623-175900.205.g2");
//      filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170627-130342.267.g2"); The same set.
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);

        // 2 bilinear quadrats with z = 0.018.
        // Tricky case which required us to to define a transition zone.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_Surf__20170313-174324.189_221.g2");
        offset.push_back(0.1);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-05);//3);//6;

        // 4 planes meeting in kinks along linear segments.
        // Tricky case which required us to to define a transition zone.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_SplineSurf__20170504-1332_kinks.g2");
        offset.push_back(3.0e-03);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-05);//3);//6;

        // A single surface with a bump in the interior. Use a negative offset value to create a self
        // intersection in the bump. Easy when using a positive offset dist, tricky when using a negative
        // offset dist. With a large offset value (< -3.0e-03) the self intersection is global.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_bump.g2");
        offset.push_back(-3.0e-03);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-05);//3);//6;

        // Self-intersections for offset dist of appr 0.3 and larger.
        filenames.push_back(data_basedir+"/test_bezier.g2");
        offset.push_back(0.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;

        // Self-int: offset=1e-02,eps=1e-03.
        // Success with removing self intersections using smoothing: offset=1e-03,eps=1e-04.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_Surf__20170404-123801.816.g2");
        offset.push_back(0.001);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;

        // Two orthogonal planes joined by a trimmed cylinder segment (w/ radius of curvature -1.38843).
        // 201706: Success after setting the twist vector to zero and reducing precond omega from 0.1 to 0.01.
        filenames.push_back(data_basedir+"/yta4.g2");
        offset.push_back(-1.5);//1.3);//(0.01);//0.1;//1.23; //0.2;
        epsgeo.push_back(1.0e-04);//3);//6;

        // Illegal bounded surface, the trim loop is CW! The offset works but the offset surface is flipped.
        filenames.push_back(data_basedir+"/TopSolid/TopSolid_BoundedSurf__20170623-173916.162.g2");
        offset.push_back(5.0e-03);
        epsgeo.push_back(1.0e-03);
#endif

#endif

        GoTools::init();

    }

public:
    vector<string> filenames;
    vector<double> offset;
    vector<double> epsgeo;
    ObjectHeader header;
    const std::string input_filename;
    const std::string output_filename;

};

BOOST_FIXTURE_TEST_CASE(offsetSurfaceSet, Config)
{
    int num_success = 0;
    int num_failures = 0;
    int num_exceptions = 0;
    for (size_t ki = 0; ki < filenames.size(); ++ki)
    {
        // Read input arguments
        std::ifstream infile(filenames[ki].c_str());
        BOOST_CHECK_MESSAGE(infile.good(), "Input file not found or file corrupt");

        vector<shared_ptr<ParamSurface> > sfs;
        while (!infile.eof())
        {
            infile >> header;
            shared_ptr<ParamSurface> sf;
            if (header.classType() == Class_SplineSurface)
            {
                sf = shared_ptr<ParamSurface>(new SplineSurface());
            }
            else if (header.classType() == Class_BoundedSurface)
            {
                sf = shared_ptr<ParamSurface>(new BoundedSurface());
            }
            else
            {
                BOOST_ERROR("Input surface type not yet supported: " << header.classType());
                continue;
            }

            sf->read(infile);

            sfs.push_back(sf);

            Utils::eatwhite(infile);
        }

        std::ofstream fileout2(input_filename);
        for (size_t kk = 0; kk < sfs.size(); ++kk)
        {
            sfs[kk]->writeStandardHeader(fileout2);
            sfs[kk]->write(fileout2);
        }

        shared_ptr<SplineSurface> offset_sf;
        OffsetSurfaceStatus status;
        try
        {
            status = OffsetSurfaceUtils::offsetSurfaceSet(sfs, offset[ki], epsgeo[ki], offset_sf);
        }
        catch (...)
        {
            std::cout << "offsetSurfaceSet(): Caught exception for filename " << filenames[ki] << std::endl;
            BOOST_ERROR("Exception caught");
            ++num_exceptions;
            continue;
        }

        BOOST_CHECK_MESSAGE(status == OFFSET_OK,
                            "offsetSurfaceSet(): Failure! Returned status (!= 0): " << status);
        if (status == OFFSET_OK)
        {
            ++num_success;
            if (offset_sf.get())
            {
                std::ofstream fileout(output_filename);
                offset_sf->writeStandardHeader(fileout);
                offset_sf->write(fileout);
            }
        }
        else
        {
            ++num_failures;
        }
    }

    BOOST_TEST_MESSAGE("\nnum files: " << filenames.size() << ", num success: " << num_success << ", num failures: " <<
                  num_failures << ", num_exceptions: " << num_exceptions);

}
<|endoftext|>


<commit_before>#ifndef FIND_NEXT_GREATER_ELEMENT_HPP
#define FIND_NEXT_GREATER_ELEMENT_HPP

#include <vector>
#include <unordered_map>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <limits>

namespace Algo::Search {

class FindNextGreaterElem {
public:
    /*
    https://leetcode.com/problems/next-greater-element-i/
    You are given two arrays (without duplicates) nums1 and nums2 where
    nums1’s elements are subset of nums2. Find all the next greater numbers
    for nums1's elements in the corresponding places of nums2.

    The Next Greater Number of a number x in nums1 is the first greater number
    to its right in nums2. If it does not exist, output -1 for this number.

    Example 1:
    Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
    Output: [-1,3,-1]
    Explanation:
        For number 4 in the first array, you cannot find the next greater
            number for it in the second array, so output -1.
        For number 1 in the first array, the next greater number for it
            in the second array is 3.
        For number 2 in the first array, there is no next greater number
            for it in the second array, so output -1.

    Example 2:
    Input: nums1 = [2,4], nums2 = [1,2,3,4].
    Output: [3,-1]
    Explanation:
        For number 2 in the first array, the next greater number for it
            in the second array is 3.
        For number 4 in the first array, there is no next greater number
            for it in the second array, so output -1.

    Note:
    All elements in nums1 and nums2 are unique.
    The length of both nums1 and nums2 would not exceed 1000.
    */

    // TC: O(n*m)
    // SC: O(1)
    static std::vector<int> FindSimple(const std::vector<int>& nums1,
                                       const std::vector<int>& nums2) {
        if (nums1.size() > nums2.size()) {
            return {};
        }

        std::vector<int> result(nums1.size(), -1);
        for (size_t i = 0; i < nums1.size(); ++i) {
            size_t pos = nums2.size();
            for (size_t j = 0; j < nums2.size(); ++j) {
                if (nums1[i] == nums2[j]) {
                    pos = j;
                    break;
                }
            }

            for (size_t j = pos + 1; j < nums2.size(); ++j) {
                if (nums1[i] < nums2[j]) {
                    result[i] = nums2[j];
                    break;
                }
            }
        }

        return result;
    }

    // TC: O(n)
    // SC: O(m)
    static std::vector<int> FindUsingStack(const std::vector<int>& nums1,
                                           const std::vector<int>& nums2) {
        if (nums1.size() > nums2.size()) {
            return {};
        }

        std::unordered_map<int, int> search_map;
        std::stack<int> st;
        for (size_t i = 0; i < nums2.size(); ++i) {
            while(!st.empty() && st.top() < nums2[i]) {
                search_map[st.top()] = nums2[i];
                st.pop();
            }

            st.push(nums2[i]);
        }

        std::vector<int> result(nums1.size(), -1);
        for (size_t i = 0; i < nums1.size(); ++i) {
            auto iter = search_map.find(nums1[i]);
            if (iter != std::end(search_map)) {
                result[i] = iter->second;
            }
        }

        return result;
    }

    /*
    https://leetcode.com/problems/next-greater-element-ii/
    Given a circular array (the next element of the last element is the first
    element of the array), print the Next Greater Number for every element.
    The Next Greater Number of a number x is the first greater number to its
    traversing-order next in the array, which means you could search circularly
    to find its next greater number. If it doesn't exist, output -1 for
    this number.

    Example 1:
    Input: [1,2,1]
    Output: [2,-1,2]
    Explanation:
    - The first 1's next greater number is 2;
    - The number 2 can't find next greater number;
    - The second 1's next greater number needs to search circularly, which is also 2.

    Note: The length of given array won't exceed 10000.
    */
    // TC: O(n)
    // SC: O(n)
    static std::vector<int> FindInCircularArray(const std::vector<int>& nums) {
        std::vector<int> result(nums.size(), -1);
        std::stack<std::pair<int, size_t>> st;
        for (size_t i = 0; i < nums.size(); ++i) {
            while(!st.empty() && st.top().first < nums[i]) {
                result[st.top().second] = nums[i];
                st.pop();
            }

            st.emplace(nums[i], i);
        }

        for (size_t i = 0; i < nums.size() && !st.empty(); ++i) {
            while(!st.empty() && st.top().first < nums[i]) {
                result[st.top().second] = nums[i];
                st.pop();
            }
        }

        return result;
    }

    /*
    https://leetcode.com/problems/next-greater-element-iii/
    Given a positive 32-bit integer n, you need to find the smallest
    32-bit integer which has exactly the same digits existing in the
    integer n and is greater in value than n. If no such positive 32-bit
    integer exists, you need to return -1.

    Example 1:
    Input: 12
    Output: 21

    Example 2:
    Input: 21
    Output: -1
    */
    // TC: O(n log n)
    // SC: O(n)
    static int FindSmallestGreaterNum(int n) {
        n = std::abs(n);
        const auto input = n;

        std::vector<int> nums = NumToVector(n);

        size_t permutation_pos = 0;
        if (!FindFirstGreaterPermutation(nums, permutation_pos)) {
            return -1;
        }

        std::sort(nums.begin() + static_cast<int>(permutation_pos) + 1,
                  nums.end());

        auto result = VectorToNum(nums);
        return result > input ? result : -1;
    }

    static std::vector<int> NumToVector(int n) {
        std::vector<int> nums;
        while(n > 0) {
            int number = n % 10;
            n /= 10;

            nums.push_back(number);
        }

        std::reverse(nums.begin(), nums.end());
        return nums;
    }

    static int VectorToNum(const std::vector<int>& v) {
        unsigned long long n = 0;
        unsigned long long multiplier = 1;
        for (size_t i = v.size() - 1; ; --i, multiplier *= 10) {
            n += static_cast<unsigned long long>(v[i]) * multiplier;
            if (i == 0) {
                break;
            }
        }

        if (n > std::numeric_limits<int>::max()) {
            return -1;
        }

        return static_cast<int>(n);
    }

    static bool FindFirstGreaterPermutation(
            std::vector<int>& v, size_t& permutation_pos) {
        if (v.empty()) {
            return false;
        }

        std::map<int, size_t> nums_map = { {*(v.rbegin()), v.size() - 1} };
        for (size_t i = v.size() - 1; ; --i)
        {
            auto iter = nums_map.upper_bound(v[i]);
            if (iter != nums_map.end()) {
                std::swap(v[i], v[iter->second]);
                permutation_pos = i;
                return true;
            }
            else {
                nums_map[v[i]] =  i;
            }

            if (i == 0) {
                break;
            }
        }

        return false;
    }
};
}

#endif // FIND_NEXT_GREATER_ELEMENT_HPP
<commit_msg>Minor code change - cast int to correct type in FindNextGreaterElement<commit_after>#ifndef FIND_NEXT_GREATER_ELEMENT_HPP
#define FIND_NEXT_GREATER_ELEMENT_HPP

#include <vector>
#include <unordered_map>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <limits>

namespace Algo::Search {

class FindNextGreaterElem {
public:
    /*
    https://leetcode.com/problems/next-greater-element-i/
    You are given two arrays (without duplicates) nums1 and nums2 where
    nums1’s elements are subset of nums2. Find all the next greater numbers
    for nums1's elements in the corresponding places of nums2.

    The Next Greater Number of a number x in nums1 is the first greater number
    to its right in nums2. If it does not exist, output -1 for this number.

    Example 1:
    Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
    Output: [-1,3,-1]
    Explanation:
        For number 4 in the first array, you cannot find the next greater
            number for it in the second array, so output -1.
        For number 1 in the first array, the next greater number for it
            in the second array is 3.
        For number 2 in the first array, there is no next greater number
            for it in the second array, so output -1.

    Example 2:
    Input: nums1 = [2,4], nums2 = [1,2,3,4].
    Output: [3,-1]
    Explanation:
        For number 2 in the first array, the next greater number for it
            in the second array is 3.
        For number 4 in the first array, there is no next greater number
            for it in the second array, so output -1.

    Note:
    All elements in nums1 and nums2 are unique.
    The length of both nums1 and nums2 would not exceed 1000.
    */

    // TC: O(n*m)
    // SC: O(1)
    static std::vector<int> FindSimple(const std::vector<int>& nums1,
                                       const std::vector<int>& nums2) {
        if (nums1.size() > nums2.size()) {
            return {};
        }

        std::vector<int> result(nums1.size(), -1);
        for (size_t i = 0; i < nums1.size(); ++i) {
            size_t pos = nums2.size();
            for (size_t j = 0; j < nums2.size(); ++j) {
                if (nums1[i] == nums2[j]) {
                    pos = j;
                    break;
                }
            }

            for (size_t j = pos + 1; j < nums2.size(); ++j) {
                if (nums1[i] < nums2[j]) {
                    result[i] = nums2[j];
                    break;
                }
            }
        }

        return result;
    }

    // TC: O(n)
    // SC: O(m)
    static std::vector<int> FindUsingStack(const std::vector<int>& nums1,
                                           const std::vector<int>& nums2) {
        if (nums1.size() > nums2.size()) {
            return {};
        }

        std::unordered_map<int, int> search_map;
        std::stack<int> st;
        for (size_t i = 0; i < nums2.size(); ++i) {
            while(!st.empty() && st.top() < nums2[i]) {
                search_map[st.top()] = nums2[i];
                st.pop();
            }

            st.push(nums2[i]);
        }

        std::vector<int> result(nums1.size(), -1);
        for (size_t i = 0; i < nums1.size(); ++i) {
            auto iter = search_map.find(nums1[i]);
            if (iter != std::end(search_map)) {
                result[i] = iter->second;
            }
        }

        return result;
    }

    /*
    https://leetcode.com/problems/next-greater-element-ii/
    Given a circular array (the next element of the last element is the first
    element of the array), print the Next Greater Number for every element.
    The Next Greater Number of a number x is the first greater number to its
    traversing-order next in the array, which means you could search circularly
    to find its next greater number. If it doesn't exist, output -1 for
    this number.

    Example 1:
    Input: [1,2,1]
    Output: [2,-1,2]
    Explanation:
    - The first 1's next greater number is 2;
    - The number 2 can't find next greater number;
    - The second 1's next greater number needs to search circularly, which is also 2.

    Note: The length of given array won't exceed 10000.
    */
    // TC: O(n)
    // SC: O(n)
    static std::vector<int> FindInCircularArray(const std::vector<int>& nums) {
        std::vector<int> result(nums.size(), -1);
        std::stack<std::pair<int, size_t>> st;
        for (size_t i = 0; i < nums.size(); ++i) {
            while(!st.empty() && st.top().first < nums[i]) {
                result[st.top().second] = nums[i];
                st.pop();
            }

            st.emplace(nums[i], i);
        }

        for (size_t i = 0; i < nums.size() && !st.empty(); ++i) {
            while(!st.empty() && st.top().first < nums[i]) {
                result[st.top().second] = nums[i];
                st.pop();
            }
        }

        return result;
    }

    /*
    https://leetcode.com/problems/next-greater-element-iii/
    Given a positive 32-bit integer n, you need to find the smallest
    32-bit integer which has exactly the same digits existing in the
    integer n and is greater in value than n. If no such positive 32-bit
    integer exists, you need to return -1.

    Example 1:
    Input: 12
    Output: 21

    Example 2:
    Input: 21
    Output: -1
    */
    // TC: O(n log n)
    // SC: O(n)
    static int FindSmallestGreaterNum(int n) {
        n = std::abs(n);
        const auto input = n;

        std::vector<int> nums = NumToVector(n);

        size_t permutation_pos = 0;
        if (!FindFirstGreaterPermutation(nums, permutation_pos)) {
            return -1;
        }

        std::sort(nums.begin() + static_cast<int>(permutation_pos) + 1,
                  nums.end());

        auto result = VectorToNum(nums);
        return result > input ? result : -1;
    }

    static std::vector<int> NumToVector(int n) {
        std::vector<int> nums;
        while(n > 0) {
            int number = n % 10;
            n /= 10;

            nums.push_back(number);
        }

        std::reverse(nums.begin(), nums.end());
        return nums;
    }

    static int VectorToNum(const std::vector<int>& v) {
        unsigned long long n = 0;
        unsigned long long multiplier = 1;
        for (size_t i = v.size() - 1; ; --i, multiplier *= 10) {
            n += static_cast<unsigned long long>(v[i]) * multiplier;
            if (i == 0) {
                break;
            }
        }

        static const auto max_int = static_cast<unsigned long long>(
            std::numeric_limits<int>::max());
        if (n > max_int) {
            return -1;
        }

        return static_cast<int>(n);
    }

    static bool FindFirstGreaterPermutation(
            std::vector<int>& v, size_t& permutation_pos) {
        if (v.empty()) {
            return false;
        }

        std::map<int, size_t> nums_map = { {*(v.rbegin()), v.size() - 1} };
        for (size_t i = v.size() - 1; ; --i)
        {
            auto iter = nums_map.upper_bound(v[i]);
            if (iter != nums_map.end()) {
                std::swap(v[i], v[iter->second]);
                permutation_pos = i;
                return true;
            }
            else {
                nums_map[v[i]] =  i;
            }

            if (i == 0) {
                break;
            }
        }

        return false;
    }
};
}

#endif // FIND_NEXT_GREATER_ELEMENT_HPP
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2015 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "spotlight.h"

// appleseed.renderer headers.
#include "renderer/global/globaltypes.h"
#include "renderer/modeling/input/inputarray.h"
#include "renderer/modeling/input/inputevaluator.h"
#include "renderer/modeling/input/source.h"
#include "renderer/utility/paramarray.h"

// appleseed.foundation headers.
#include "foundation/math/sampling/mappings.h"
#include "foundation/math/distance.h"
#include "foundation/math/matrix.h"
#include "foundation/math/scalar.h"
#include "foundation/math/transform.h"
#include "foundation/math/vector.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/containers/specializedarrays.h"

// Standard headers.
#include <cmath>

// Forward declarations.
namespace foundation    { class IAbortSwitch; }
namespace renderer      { class Assembly; }
namespace renderer      { class Project; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Spot light.
    //

    const char* Model = "spot_light";

    class SpotLight
      : public Light
    {
      public:
        SpotLight(
            const char*         name,
            const ParamArray&   params)
          : Light(name, params)
        {
            m_inputs.declare("intensity", InputFormatSpectralIlluminance);
            m_inputs.declare("intensity_multiplier", InputFormatScalar, "1.0");
            m_inputs.declare("exposure", InputFormatScalar, "0.0");
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return Model;
        }

        virtual bool on_frame_begin(
            const Project&      project,
            const Assembly&     assembly,
            IAbortSwitch*       abort_switch) APPLESEED_OVERRIDE
        {
            if (!Light::on_frame_begin(project, assembly, abort_switch))
                return false;

            m_intensity_source = m_inputs.source("intensity");
            m_intensity_multiplier_source = m_inputs.source("intensity_multiplier");
            m_exposure_source = m_inputs.source("exposure");
            check_non_zero_emission(m_intensity_source, m_intensity_multiplier_source);

            const double inner_half_angle = deg_to_rad(m_params.get_required<double>("inner_angle", 20.0) / 2.0);
            const double outer_half_angle = deg_to_rad(m_params.get_required<double>("outer_angle", 30.0) / 2.0);
            const double tilt_angle = deg_to_rad(m_params.get_optional<double>("tilt_angle", 0.0));

            m_cos_inner_half_angle = cos(inner_half_angle);
            m_cos_outer_half_angle = cos(outer_half_angle);
            m_rcp_screen_half_size = 1.0 / tan(outer_half_angle);
            m_up = Vector3d(sin(tilt_angle), cos(tilt_angle), 0.0);

            return true;
        }

        virtual void sample(
            InputEvaluator&     input_evaluator,
            const Transformd&   light_transform,
            const Vector2d&     s,
            Vector3d&           position,
            Vector3d&           outgoing,
            Spectrum&           value,
            double&             probability) const APPLESEED_OVERRIDE
        {
            position = light_transform.get_parent_origin();
            outgoing = light_transform.vector_to_parent(rotate_minus_pi_around_x(sample_cone_uniform(s, m_cos_outer_half_angle)));
            probability = sample_cone_uniform_pdf(m_cos_outer_half_angle);

            const Vector3d axis = -normalize(light_transform.get_parent_z());

            compute_radiance(input_evaluator, light_transform, axis, outgoing, value);
        }

        virtual void evaluate(
            InputEvaluator&     input_evaluator,
            const Transformd&   light_transform,
            const Vector3d&     target,
            Vector3d&           position,
            Vector3d&           outgoing,
            Spectrum&           value) const APPLESEED_OVERRIDE
        {
            position = light_transform.get_parent_origin();
            outgoing = normalize(target - position);

            const Vector3d axis = -normalize(light_transform.get_parent_z());

            if (dot(outgoing, axis) > m_cos_outer_half_angle)
                compute_radiance(input_evaluator, light_transform, axis, outgoing, value);
            else value.set(0.0f);
        }

        double compute_distance_attenuation(
            const Vector3d&     target,
            const Vector3d&     position) const APPLESEED_OVERRIDE
        {
            return 1.0 / square_distance(target, position);
        }

      private:
        APPLESEED_DECLARE_INPUT_VALUES(InputValues)
        {
            Spectrum    m_intensity;                // emitted intensity in W.sr^-1
            double      m_intensity_multiplier;     // emitted intensity multiplier
            double      m_exposure;                 // emitted intensity multiplier in f-stops
        };

        const Source*   m_intensity_source;
        const Source*   m_intensity_multiplier_source;
        const Source*   m_exposure_source;

        double          m_cos_inner_half_angle;
        double          m_cos_outer_half_angle;
        double          m_rcp_screen_half_size;

        Vector3d        m_up;                       // light space

        static Vector3d rotate_minus_pi_around_x(const Vector3d& v)
        {
            return Vector3d(v[0], v[2], -v[1]);
        }

        void compute_radiance(
            InputEvaluator&     input_evaluator,
            const Transformd&   light_transform,
            const Vector3d&     axis,
            const Vector3d&     outgoing,
            Spectrum&           radiance) const
        {
            const Vector3d up = light_transform.vector_to_parent(m_up);
            const Vector3d v = -axis;
            const Vector3d u = normalize(cross(up, v));
            const Vector3d n = cross(v, u);

            const double cos_theta = dot(outgoing, axis);
            assert(cos_theta > m_cos_outer_half_angle);

            const Vector3d d = outgoing / cos_theta - axis;
            const double x = dot(d, u) * m_rcp_screen_half_size;
            const double y = dot(d, n) * m_rcp_screen_half_size;
            const Vector2d uv(0.5 * (x + 1.0), 0.5 * (y + 1.0));

            const InputValues* values = input_evaluator.evaluate<InputValues>(m_inputs, uv);
            radiance = values->m_intensity;
            radiance *=
                static_cast<float>(values->m_intensity_multiplier * pow(2.0, values->m_exposure));

            if (cos_theta < m_cos_inner_half_angle)
            {
                radiance *=
                    static_cast<float>(
                        smoothstep(m_cos_outer_half_angle, m_cos_inner_half_angle, cos_theta));
            }
        }
    };
}

//
// SpotLightFactory class implementation.
//

const char* SpotLightFactory::get_model() const
{
    return Model;
}

Dictionary SpotLightFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Spot Light")
            .insert("help", "A light source that emits light in a cone of directions from a point");
}

DictionaryArray SpotLightFactory::get_input_metadata() const
{
    DictionaryArray metadata;

    metadata.push_back(
        Dictionary()
            .insert("name", "intensity")
            .insert("label", "Intensity")
            .insert("type", "colormap")
            .insert("entity_types",
                Dictionary()
                    .insert("color", "Colors")
                    .insert("texture_instance", "Textures"))
            .insert("use", "required")
            .insert("default", "1.0")
            .insert("help", "Light intensity"));

    metadata.push_back(
        Dictionary()
            .insert("name", "intensity_multiplier")
            .insert("label", "Intensity Multiplier")
            .insert("type", "colormap")
            .insert("entity_types",
                Dictionary().insert("texture_instance", "Textures"))
            .insert("use", "optional")
            .insert("default", "1.0")
            .insert("help", "Light intensity multiplier"));

    metadata.push_back(
        Dictionary()
            .insert("name", "exposure")
            .insert("label", "Exposure")
            .insert("type", "numeric")
            .insert("use", "optional")
            .insert("default", "0.0")
            .insert("min_value", "-64.0")
            .insert("max_value", "64.0")
            .insert("help", "Light exposure"));

    metadata.push_back(
        Dictionary()
            .insert("name", "inner_angle")
            .insert("label", "Inner Angle")
            .insert("type", "numeric")
            .insert("min_value", "-180.0")
            .insert("max_value", "180.0")
            .insert("use", "required")
            .insert("default", "20.0")
            .insert("help", "Cone distribution inner angle"));

    metadata.push_back(
        Dictionary()
            .insert("name", "outer_angle")
            .insert("label", "Outer Angle")
            .insert("type", "numeric")
            .insert("min_value", "-180.0")
            .insert("max_value", "180.0")
            .insert("use", "required")
            .insert("default", "30.0")
            .insert("help", "Cone distribution outer angle"));

    metadata.push_back(
        Dictionary()
            .insert("name", "tilt_angle")
            .insert("label", "Tilt Angle")
            .insert("type", "numeric")
            .insert("min_value", "-360.0")
            .insert("max_value", "360.0")
            .insert("use", "optional")
            .insert("default", "0.0")
            .insert("help", "Rotate the spot light around its axis; only useful when using the light intensity is textured (gobo)"));

    add_common_input_metadata(metadata);

    return metadata;
}

auto_release_ptr<Light> SpotLightFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<Light>(new SpotLight(name, params));
}

}   // namespace renderer
<commit_msg>Exposure metadata for spot lights should be of type colormap.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2015 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "spotlight.h"

// appleseed.renderer headers.
#include "renderer/global/globaltypes.h"
#include "renderer/modeling/input/inputarray.h"
#include "renderer/modeling/input/inputevaluator.h"
#include "renderer/modeling/input/source.h"
#include "renderer/utility/paramarray.h"

// appleseed.foundation headers.
#include "foundation/math/sampling/mappings.h"
#include "foundation/math/distance.h"
#include "foundation/math/matrix.h"
#include "foundation/math/scalar.h"
#include "foundation/math/transform.h"
#include "foundation/math/vector.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/containers/specializedarrays.h"

// Standard headers.
#include <cmath>

// Forward declarations.
namespace foundation    { class IAbortSwitch; }
namespace renderer      { class Assembly; }
namespace renderer      { class Project; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Spot light.
    //

    const char* Model = "spot_light";

    class SpotLight
      : public Light
    {
      public:
        SpotLight(
            const char*         name,
            const ParamArray&   params)
          : Light(name, params)
        {
            m_inputs.declare("intensity", InputFormatSpectralIlluminance);
            m_inputs.declare("intensity_multiplier", InputFormatScalar, "1.0");
            m_inputs.declare("exposure", InputFormatScalar, "0.0");
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return Model;
        }

        virtual bool on_frame_begin(
            const Project&      project,
            const Assembly&     assembly,
            IAbortSwitch*       abort_switch) APPLESEED_OVERRIDE
        {
            if (!Light::on_frame_begin(project, assembly, abort_switch))
                return false;

            m_intensity_source = m_inputs.source("intensity");
            m_intensity_multiplier_source = m_inputs.source("intensity_multiplier");
            m_exposure_source = m_inputs.source("exposure");
            check_non_zero_emission(m_intensity_source, m_intensity_multiplier_source);

            const double inner_half_angle = deg_to_rad(m_params.get_required<double>("inner_angle", 20.0) / 2.0);
            const double outer_half_angle = deg_to_rad(m_params.get_required<double>("outer_angle", 30.0) / 2.0);
            const double tilt_angle = deg_to_rad(m_params.get_optional<double>("tilt_angle", 0.0));

            m_cos_inner_half_angle = cos(inner_half_angle);
            m_cos_outer_half_angle = cos(outer_half_angle);
            m_rcp_screen_half_size = 1.0 / tan(outer_half_angle);
            m_up = Vector3d(sin(tilt_angle), cos(tilt_angle), 0.0);

            return true;
        }

        virtual void sample(
            InputEvaluator&     input_evaluator,
            const Transformd&   light_transform,
            const Vector2d&     s,
            Vector3d&           position,
            Vector3d&           outgoing,
            Spectrum&           value,
            double&             probability) const APPLESEED_OVERRIDE
        {
            position = light_transform.get_parent_origin();
            outgoing = light_transform.vector_to_parent(rotate_minus_pi_around_x(sample_cone_uniform(s, m_cos_outer_half_angle)));
            probability = sample_cone_uniform_pdf(m_cos_outer_half_angle);

            const Vector3d axis = -normalize(light_transform.get_parent_z());

            compute_radiance(input_evaluator, light_transform, axis, outgoing, value);
        }

        virtual void evaluate(
            InputEvaluator&     input_evaluator,
            const Transformd&   light_transform,
            const Vector3d&     target,
            Vector3d&           position,
            Vector3d&           outgoing,
            Spectrum&           value) const APPLESEED_OVERRIDE
        {
            position = light_transform.get_parent_origin();
            outgoing = normalize(target - position);

            const Vector3d axis = -normalize(light_transform.get_parent_z());

            if (dot(outgoing, axis) > m_cos_outer_half_angle)
                compute_radiance(input_evaluator, light_transform, axis, outgoing, value);
            else value.set(0.0f);
        }

        double compute_distance_attenuation(
            const Vector3d&     target,
            const Vector3d&     position) const APPLESEED_OVERRIDE
        {
            return 1.0 / square_distance(target, position);
        }

      private:
        APPLESEED_DECLARE_INPUT_VALUES(InputValues)
        {
            Spectrum    m_intensity;                // emitted intensity in W.sr^-1
            double      m_intensity_multiplier;     // emitted intensity multiplier
            double      m_exposure;                 // emitted intensity multiplier in f-stops
        };

        const Source*   m_intensity_source;
        const Source*   m_intensity_multiplier_source;
        const Source*   m_exposure_source;

        double          m_cos_inner_half_angle;
        double          m_cos_outer_half_angle;
        double          m_rcp_screen_half_size;

        Vector3d        m_up;                       // light space

        static Vector3d rotate_minus_pi_around_x(const Vector3d& v)
        {
            return Vector3d(v[0], v[2], -v[1]);
        }

        void compute_radiance(
            InputEvaluator&     input_evaluator,
            const Transformd&   light_transform,
            const Vector3d&     axis,
            const Vector3d&     outgoing,
            Spectrum&           radiance) const
        {
            const Vector3d up = light_transform.vector_to_parent(m_up);
            const Vector3d v = -axis;
            const Vector3d u = normalize(cross(up, v));
            const Vector3d n = cross(v, u);

            const double cos_theta = dot(outgoing, axis);
            assert(cos_theta > m_cos_outer_half_angle);

            const Vector3d d = outgoing / cos_theta - axis;
            const double x = dot(d, u) * m_rcp_screen_half_size;
            const double y = dot(d, n) * m_rcp_screen_half_size;
            const Vector2d uv(0.5 * (x + 1.0), 0.5 * (y + 1.0));

            const InputValues* values = input_evaluator.evaluate<InputValues>(m_inputs, uv);
            radiance = values->m_intensity;
            radiance *=
                static_cast<float>(values->m_intensity_multiplier * pow(2.0, values->m_exposure));

            if (cos_theta < m_cos_inner_half_angle)
            {
                radiance *=
                    static_cast<float>(
                        smoothstep(m_cos_outer_half_angle, m_cos_inner_half_angle, cos_theta));
            }
        }
    };
}

//
// SpotLightFactory class implementation.
//

const char* SpotLightFactory::get_model() const
{
    return Model;
}

Dictionary SpotLightFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Spot Light")
            .insert("help", "A light source that emits light in a cone of directions from a point");
}

DictionaryArray SpotLightFactory::get_input_metadata() const
{
    DictionaryArray metadata;

    metadata.push_back(
        Dictionary()
            .insert("name", "intensity")
            .insert("label", "Intensity")
            .insert("type", "colormap")
            .insert("entity_types",
                Dictionary()
                    .insert("color", "Colors")
                    .insert("texture_instance", "Textures"))
            .insert("use", "required")
            .insert("default", "1.0")
            .insert("help", "Light intensity"));

    metadata.push_back(
        Dictionary()
            .insert("name", "intensity_multiplier")
            .insert("label", "Intensity Multiplier")
            .insert("type", "colormap")
            .insert("entity_types",
                Dictionary().insert("texture_instance", "Textures"))
            .insert("use", "optional")
            .insert("default", "1.0")
            .insert("help", "Light intensity multiplier"));

    metadata.push_back(
        Dictionary()
            .insert("name", "exposure")
            .insert("label", "Exposure")
            .insert("type", "colormap")
            .insert("entity_types",
                Dictionary().insert("texture_instance", "Textures"))
            .insert("use", "optional")
            .insert("default", "0.0")
            .insert("help", "Light exposure"));

    metadata.push_back(
        Dictionary()
            .insert("name", "inner_angle")
            .insert("label", "Inner Angle")
            .insert("type", "numeric")
            .insert("min_value", "-180.0")
            .insert("max_value", "180.0")
            .insert("use", "required")
            .insert("default", "20.0")
            .insert("help", "Cone distribution inner angle"));

    metadata.push_back(
        Dictionary()
            .insert("name", "outer_angle")
            .insert("label", "Outer Angle")
            .insert("type", "numeric")
            .insert("min_value", "-180.0")
            .insert("max_value", "180.0")
            .insert("use", "required")
            .insert("default", "30.0")
            .insert("help", "Cone distribution outer angle"));

    metadata.push_back(
        Dictionary()
            .insert("name", "tilt_angle")
            .insert("label", "Tilt Angle")
            .insert("type", "numeric")
            .insert("min_value", "-360.0")
            .insert("max_value", "360.0")
            .insert("use", "optional")
            .insert("default", "0.0")
            .insert("help", "Rotate the spot light around its axis; only useful when using the light intensity is textured (gobo)"));

    add_common_input_metadata(metadata);

    return metadata;
}

auto_release_ptr<Light> SpotLightFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<Light>(new SpotLight(name, params));
}

}   // namespace renderer
<|endoftext|>


<commit_before>#pragma once
#ifndef LIGHTPTR_HPP
# define LIGHTPTR_HPP

#include <cassert>

#include <atomic>

#include <memory>

#include <utility>

#include <type_traits>

namespace generic
{

namespace detail
{
  using counter_type = unsigned;

  using atomic_type = ::std::atomic<counter_type>;

  template <typename T>
  using deleter_type = void (*)(T*);

  template <typename U>
  struct ref_type
  {
    using type = U&;
  };

  template <>
  struct ref_type<void>
  {
    using type = void;
  };
}

template <typename T>
struct light_ptr
{
  template <typename U, typename V>
  struct deletion_type
  {
    using type = V;
  };

  template <typename U, typename V>
  struct deletion_type<U[], V>
  {
    using type = V[];
  };

  template <typename U, typename V, ::std::size_t N>
  struct deletion_type<U[N], V>
  {
    using type = V[];
  };

  template <typename U>
  struct remove_array
  {
    using type = U;
  };

  template <typename U>
  struct remove_array<U[]>
  {
    using type = U;
  };

  template <typename U, ::std::size_t N>
  struct remove_array<U[N]>
  {
    using type = U;
  };

  using element_type = typename remove_array<T>::type;

  using deleter_type = detail::deleter_type<element_type>;

  struct counter_base
  {
    using invoker_type = void (*)(counter_base*, element_type*);

    explicit counter_base(detail::counter_type c,
      invoker_type invoker) noexcept :
      counter_(c),
      invoker_(invoker)
    {
    }

    template <typename U>
    typename ::std::enable_if<!::std::is_void<U>{}>::type
    dec_ref(U* const ptr)
    {
      if (detail::counter_type(1) ==
        counter_.fetch_sub(detail::counter_type(1),
          ::std::memory_order_relaxed))
      {
        typedef char type_must_be_complete[sizeof(U) ? 1 : -1];
        (void)sizeof(type_must_be_complete);
        invoker_(this, ptr);
      }
      // else do nothing
    }

    template <typename U>
    typename ::std::enable_if<::std::is_void<U>{}>::type
    dec_ref(U* const ptr)
    {
      if (detail::counter_type(1) ==
        counter_.fetch_sub(detail::counter_type(1),
          ::std::memory_order_relaxed))
      {
        invoker_(this, ptr);
      }
      // else do nothing
    }

    void inc_ref() noexcept
    {
      //assert(counter_ptr);
      counter_.fetch_add(detail::counter_type(1),
        ::std::memory_order_relaxed);
    }

    detail::atomic_type counter_{};

    invoker_type invoker_;
  };

  template <typename U>
  struct counter : counter_base
  {
    explicit counter(detail::counter_type const c, U&& d) noexcept :
      counter_base(c, invoker),
      d_(::std::forward<U>(d))
    {
    }

  private:
    static void invoker(counter_base* const ptr, element_type* e)
    {
      auto const c(static_cast<counter<U>*>(ptr));

      typename ::std::decay<U>::type const d(::std::move(c->d_));

      delete c;

      d(e);
    }

  private:
    typename ::std::decay<U>::type d_;
  };

  light_ptr() = default;

  template <typename U, typename D>
  explicit light_ptr(U* const p, D&& d = default_deleter<U>)
  {
    reset(p, ::std::forward<D>(d));
  }

  ~light_ptr()
  {
    if (counter_)
    {
      counter_->dec_ref(ptr_);
    }
    // else do nothing
  }

  light_ptr(light_ptr const& other) { *this = other; }

  light_ptr(light_ptr&& other) noexcept { *this = ::std::move(other); }

  light_ptr& operator=(light_ptr const& rhs)
  {
    if (*this != rhs)
    {
      if (counter_)
      {
        counter_->dec_ref(ptr_);
      }
      // else do nothing

      counter_ = rhs.counter_;
      ptr_ = rhs.ptr_;

      if (counter_)
      {
        counter_->inc_ref();
      }
      // else do nothing
    }
    // else do nothing

    return *this;
  }

  light_ptr& operator=(light_ptr&& rhs) noexcept
  {
    counter_ = rhs.counter_;
    ptr_ = rhs.ptr_;

    rhs.counter_ = nullptr;
    rhs.ptr_ = nullptr;

    return *this;
  }

  light_ptr& operator=(::std::nullptr_t const) noexcept { reset(); }

  bool operator<(light_ptr const& rhs) const noexcept
  {
    return get() < rhs.get();
  }

  bool operator==(light_ptr const& rhs) const noexcept
  {
    return counter_ == rhs.counter_;
  }

  bool operator!=(light_ptr const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return ptr_;
  }

  explicit operator bool() const noexcept { return ptr_; }

  typename detail::ref_type<T>::type
  operator*() const noexcept
  {
    return *static_cast<T*>(static_cast<void*>(ptr_));
  }

  T* operator->() const noexcept
  {
    return static_cast<T*>(static_cast<void*>(ptr_));
  }

  element_type* get() const noexcept { return ptr_; }

  void reset() { reset(nullptr); }

  void reset(::std::nullptr_t const)
  {
    if (counter_)
    {
      counter_->dec_ref(ptr_);

      counter_ = {};
    }
    // else do nothing

    ptr_ = {};
  }

  template <typename U>
  static void default_deleter(element_type* const p)
  {
    ::std::default_delete<typename deletion_type<T, U>::type>()(
      static_cast<U*>(p));
  }

  template <typename U, typename D>
  void reset(U* const p, D&& d = default_deleter<U>)
  {
    if (counter_)
    {
      counter_->dec_ref(ptr_);
    }
    // else do nothing

    counter_ = new counter<D>(detail::counter_type(1), ::std::forward<D>(d));

    ptr_ = p;
  }

  void swap(light_ptr& other) noexcept
  {
    ::std::swap(counter_, other.counter_);
    ::std::swap(ptr_, other.ptr_);
  }

  bool unique() const noexcept
  {
    return detail::counter_type(1) == use_count();
  }

  detail::counter_type use_count() const noexcept
  {
    return counter_ ?
      counter_->counter_.load(::std::memory_order_relaxed) :
      detail::counter_type{};
  }

private:
  counter_base* counter_{};

  element_type* ptr_{};
};

template<class T, class ...Args>
inline light_ptr<T> make_light(Args&& ...args)
{
  return light_ptr<T>(new T(::std::forward<Args>(args)...));
}

}

namespace std
{
  template <typename T>
  struct hash<::generic::light_ptr<T> >
  {
    size_t operator()(::generic::light_ptr<T> const& l) const noexcept
    {
      return hash<typename ::generic::light_ptr<T>::element_type*>()(l.get());
    }
  };
}

#endif // LIGHTPTR_HPP
<commit_msg>some fixes<commit_after>#pragma once
#ifndef LIGHTPTR_HPP
# define LIGHTPTR_HPP

#include <cassert>

#include <atomic>

#include <memory>

#include <utility>

#include <type_traits>

namespace generic
{

namespace detail
{
  using counter_type = unsigned;

  using atomic_type = ::std::atomic<counter_type>;

  template <typename T>
  using deleter_type = void (*)(T*);

  template <typename U>
  struct ref_type
  {
    using type = U&;
  };

  template <>
  struct ref_type<void>
  {
    using type = void;
  };
}

template <typename T>
struct light_ptr
{
  template <typename U, typename V>
  struct deletion_type
  {
    using type = V;
  };

  template <typename U, typename V>
  struct deletion_type<U[], V>
  {
    using type = V[];
  };

  template <typename U, typename V, ::std::size_t N>
  struct deletion_type<U[N], V>
  {
    using type = V[];
  };

  template <typename U>
  struct remove_array
  {
    using type = U;
  };

  template <typename U>
  struct remove_array<U[]>
  {
    using type = U;
  };

  template <typename U, ::std::size_t N>
  struct remove_array<U[N]>
  {
    using type = U;
  };

  using element_type = typename remove_array<T>::type;

  using deleter_type = detail::deleter_type<element_type>;

  struct counter_base
  {
    using invoker_type = void (*)(counter_base*, element_type*);

    explicit counter_base(detail::counter_type c,
      invoker_type invoker) noexcept :
      counter_(c),
      invoker_(invoker)
    {
    }

    template <typename U>
    typename ::std::enable_if<!::std::is_void<U>{}>::type
    dec_ref(U* const ptr)
    {
      if (detail::counter_type(1) ==
        counter_.fetch_sub(detail::counter_type(1),
          ::std::memory_order_relaxed))
      {
        typedef char type_must_be_complete[sizeof(U) ? 1 : -1];
        (void)sizeof(type_must_be_complete);
        invoker_(this, ptr);
      }
      // else do nothing
    }

    template <typename U>
    typename ::std::enable_if<::std::is_void<U>{}>::type
    dec_ref(U* const ptr)
    {
      if (detail::counter_type(1) ==
        counter_.fetch_sub(detail::counter_type(1),
          ::std::memory_order_relaxed))
      {
        invoker_(this, ptr);
      }
      // else do nothing
    }

    void inc_ref() noexcept
    {
      //assert(counter_ptr);
      counter_.fetch_add(detail::counter_type(1),
        ::std::memory_order_relaxed);
    }

    detail::atomic_type counter_{};

    invoker_type invoker_;
  };

  template <typename U>
  struct counter : counter_base
  {
    explicit counter(detail::counter_type const c, U&& d) noexcept :
      counter_base(c, invoker),
      d_(::std::forward<U>(d))
    {
    }

  private:
    static void invoker(counter_base* const ptr, element_type* e)
    {
      auto const c(static_cast<counter<U>*>(ptr));

      typename ::std::decay<U>::type const d(::std::move(c->d_));

      delete c;

      d(e);
    }

  private:
    typename ::std::decay<U>::type d_;
  };

  light_ptr() = default;

  template <typename U>
  static void default_deleter(element_type* const p)
  {
    ::std::default_delete<typename deletion_type<T, U>::type>()(
      static_cast<U*>(p));
  }

  template <typename U, typename D = decltype(&default_deleter<U>)>
  explicit light_ptr(U* p, D&& d = default_deleter<U>)
  {
    reset(p, ::std::forward<D>(d));
  }

  ~light_ptr()
  {
    if (counter_)
    {
      counter_->dec_ref(ptr_);
    }
    // else do nothing
  }

  light_ptr(light_ptr const& other) { *this = other; }

  light_ptr(light_ptr&& other) noexcept { *this = ::std::move(other); }

  light_ptr& operator=(light_ptr const& rhs)
  {
    if (*this != rhs)
    {
      if (counter_)
      {
        counter_->dec_ref(ptr_);
      }
      // else do nothing

      counter_ = rhs.counter_;
      ptr_ = rhs.ptr_;

      if (counter_)
      {
        counter_->inc_ref();
      }
      // else do nothing
    }
    // else do nothing

    return *this;
  }

  light_ptr& operator=(light_ptr&& rhs) noexcept
  {
    counter_ = rhs.counter_;
    ptr_ = rhs.ptr_;

    rhs.counter_ = nullptr;
    rhs.ptr_ = nullptr;

    return *this;
  }

  light_ptr& operator=(::std::nullptr_t const) noexcept { reset(); }

  bool operator<(light_ptr const& rhs) const noexcept
  {
    return get() < rhs.get();
  }

  bool operator==(light_ptr const& rhs) const noexcept
  {
    return counter_ == rhs.counter_;
  }

  bool operator!=(light_ptr const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return ptr_;
  }

  explicit operator bool() const noexcept { return ptr_; }

  typename detail::ref_type<T>::type
  operator*() const noexcept
  {
    return *static_cast<T*>(static_cast<void*>(ptr_));
  }

  T* operator->() const noexcept
  {
    return static_cast<T*>(static_cast<void*>(ptr_));
  }

  element_type* get() const noexcept { return ptr_; }

  void reset() { reset(nullptr); }

  void reset(::std::nullptr_t const)
  {
    if (counter_)
    {
      counter_->dec_ref(ptr_);

      counter_ = {};
    }
    // else do nothing

    ptr_ = {};
  }

  template <typename U, typename D = decltype(&default_deleter<U>)>
  void reset(U* const p, D&& d = default_deleter<U>)
  {
    if (counter_)
    {
      counter_->dec_ref(ptr_);
    }
    // else do nothing

    counter_ = new counter<D>(detail::counter_type(1), ::std::forward<D>(d));

    ptr_ = p;
  }

  void swap(light_ptr& other) noexcept
  {
    ::std::swap(counter_, other.counter_);
    ::std::swap(ptr_, other.ptr_);
  }

  bool unique() const noexcept
  {
    return detail::counter_type(1) == use_count();
  }

  detail::counter_type use_count() const noexcept
  {
    return counter_ ?
      counter_->counter_.load(::std::memory_order_relaxed) :
      detail::counter_type{};
  }

private:
  counter_base* counter_{};

  element_type* ptr_{};
};

template<class T, class ...Args>
inline light_ptr<T> make_light(Args&& ...args)
{
  return light_ptr<T>(new T(::std::forward<Args>(args)...));
}

}

namespace std
{
  template <typename T>
  struct hash<::generic::light_ptr<T> >
  {
    size_t operator()(::generic::light_ptr<T> const& l) const noexcept
    {
      return hash<typename ::generic::light_ptr<T>::element_type*>()(l.get());
    }
  };
}

#endif // LIGHTPTR_HPP
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <unistd.h>
#include <dirent.h>
#include <fstream>
#include <queue>
#include "omp.h"

struct Settings {
	Settings(): extract(),
				compress(),
   				verbose(),
				output() {}
	bool extract;
	bool compress;
	bool verbose;
	bool output;
	std::string name;
};

void helpCheck(char *argv[]) {
	if (argv[1] == std::string("-h") || argv[1] == std::string("--help")) {
		std::cout << "\nptxv - Parallel Tar XZ by Ryan Chui (2017)\n" << std::endl;
		exit(0);
	}
}

void getSettings(int argc, char *argv[], Settings *instance) {
	std::queue<std::string> settings;
	for (int i = 1; i < argc; ++i) {
		settings.push(argv[i]);
	}

	while (!settings.empty()) {
		std::string arg = settings.front();

		if (arg == "-x") {
			if ((*instance).compress) {
				std::cout << "ERROR: ptxz cannot both compress and extract. \"ptxz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).extract = true;
		} else if (arg == "-c") {
			if ((*instance).extract) {
				std::cout << "ERROR: ptxz cannot both compress and extract. \"ptxz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).compress = true;
		} else if (arg == "-v"){
			(*instance).verbose = true;
		} else if (arg == "-o") {
			(*instance).output = true;
		} else {
			if (settings.size() > 1) {
				std::cout << "ERROR: ptxz was called incorrectly. \"ptxz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).output = true;
			(*instance).name = arg;
		}

		settings.pop();
	}

	if (!(*instance).output) {
		std::cout << "ERROR: No output file name given. \"ptxz -h\" for help." << std::endl;
	}
}

void findAll(int *numFiles, const char *cwd) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					findAll(numFiles, filePath.c_str());
				} else {
					*numFiles += 1;
				}
			}
		}
		closedir(dir);
	}
}

void getPaths(std::vector<std::string> *filePaths, const char *cwd, std::string rootPath) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					getPaths(filePaths, filePath.c_str(), rootPath + fileBuff + "/");
				} else {
					filePaths->push_back(rootPath + fileBuff);
				}
			}
		}
		closedir(dir);
	}
}

void compression(std::vector<std::string> *filePaths) {
	unsigned long long int filePathSize = filePaths->size();
	unsigned long long int blockSize = (filePathSize / (omp_get_max_threads() * 10)) + 1;
	std::vector<std::string> *tarNames = new std::vector<std::string>();

	#pragma omp parallel for schedule(dynamic)
	for (int i = 0; i < omp_get_max_threads() * 10; ++i) {
		unsigned long long int start = blockSize * i;
		if (start < filePathSize) {
			std::string xzCommand = "XZ_OPT=-1 tar cJf test." + std::to_string(i) + ".tar.xz";
			for (unsigned long long int j = start; j < std::min(start + blockSize, filePathSize); ++j) {
				xzCommand += " " + filePaths->at(j);
			}
			system(xzCommand.c_str());

			#pragma omp crtical
			{
				tarNames->push_back("test." + std::to_string(i) + ".tar.xz");
			}
		}
	}

	std::string tarCommand = "tar cf ptxz.output.tar";
	for (int i = 0; i < tarNames->size(); ++i) {
		tarCommand += " " + tarNames->at(i);
	}
	system(tarCommand.c_str());

	std::string rmCommand = "rm";
	for (int i = 0; i < tarNames->size(); ++i) {
		rmCommand += " " + tarNames->at(i);
	}
	system(rmCommand.c_str());

	delete(tarNames);
}

char cwd [PATH_MAX];

int main(int argc, char *argv[]) {
	Settings *instance = new Settings;
	int *numFiles = new int(0);

	helpCheck(argv);
	getSettings(argc, argv, instance);

	getcwd(cwd, PATH_MAX);
	findAll(numFiles, cwd);

	std::vector<std::string> *filePaths = new std::vector<std::string>();

	getPaths(filePaths, cwd, "");
	compression(filePaths);

	delete(instance);
	delete(numFiles);
	delete(filePaths);
	return 0;
}
<commit_msg>Added argc check<commit_after>#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <unistd.h>
#include <dirent.h>
#include <fstream>
#include <queue>
#include "omp.h"

struct Settings {
	Settings(): extract(),
				compress(),
   				verbose(),
				output() {}
	bool extract;
	bool compress;
	bool verbose;
	bool output;
	std::string name;
};

void helpCheck(char *argv[]) {
	if (argv[1] == std::string("-h") || argv[1] == std::string("--help")) {
		std::cout << "\nptxv - Parallel Tar XZ by Ryan Chui (2017)\n" << std::endl;
		exit(0);
	}
}

void getSettings(int argc, char *argv[], Settings *instance) {
	std::queue<std::string> settings;
	if (argc == 1) {
		std::cout << "ERROR: ptxz was passed no parameters. \"ptxz -h\" for help." << std::endl;
	}
	for (int i = 1; i < argc; ++i) {
		settings.push(argv[i]);
	}

	while (!settings.empty()) {
		std::string arg = settings.front();

		if (arg == "-x") {
			if ((*instance).compress) {
				std::cout << "ERROR: ptxz cannot both compress and extract. \"ptxz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).extract = true;
		} else if (arg == "-c") {
			if ((*instance).extract) {
				std::cout << "ERROR: ptxz cannot both compress and extract. \"ptxz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).compress = true;
		} else if (arg == "-v"){
			(*instance).verbose = true;
		} else if (arg == "-o") {
			(*instance).output = true;
		} else {
			if (settings.size() > 1) {
				std::cout << "ERROR: ptxz was called incorrectly. \"ptxz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).output = true;
			(*instance).name = arg;
		}

		settings.pop();
	}

	if (!(*instance).output) {
		std::cout << "ERROR: No output file name given. \"ptxz -h\" for help." << std::endl;
	}
}

void findAll(int *numFiles, const char *cwd) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					findAll(numFiles, filePath.c_str());
				} else {
					*numFiles += 1;
				}
			}
		}
		closedir(dir);
	}
}

void getPaths(std::vector<std::string> *filePaths, const char *cwd, std::string rootPath) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					getPaths(filePaths, filePath.c_str(), rootPath + fileBuff + "/");
				} else {
					filePaths->push_back(rootPath + fileBuff);
				}
			}
		}
		closedir(dir);
	}
}

void compression(std::vector<std::string> *filePaths) {
	unsigned long long int filePathSize = filePaths->size();
	unsigned long long int blockSize = (filePathSize / (omp_get_max_threads() * 10)) + 1;
	std::vector<std::string> *tarNames = new std::vector<std::string>();

	#pragma omp parallel for schedule(dynamic)
	for (int i = 0; i < omp_get_max_threads() * 10; ++i) {
		unsigned long long int start = blockSize * i;
		if (start < filePathSize) {
			std::string xzCommand = "XZ_OPT=-1 tar cJf test." + std::to_string(i) + ".tar.xz";
			for (unsigned long long int j = start; j < std::min(start + blockSize, filePathSize); ++j) {
				xzCommand += " " + filePaths->at(j);
			}
			system(xzCommand.c_str());

			#pragma omp crtical
			{
				tarNames->push_back("test." + std::to_string(i) + ".tar.xz");
			}
		}
	}

	std::string tarCommand = "tar cf ptxz.output.tar";
	for (int i = 0; i < tarNames->size(); ++i) {
		tarCommand += " " + tarNames->at(i);
	}
	system(tarCommand.c_str());

	std::string rmCommand = "rm";
	for (int i = 0; i < tarNames->size(); ++i) {
		rmCommand += " " + tarNames->at(i);
	}
	system(rmCommand.c_str());

	delete(tarNames);
}

char cwd [PATH_MAX];

int main(int argc, char *argv[]) {
	Settings *instance = new Settings;
	int *numFiles = new int(0);

	helpCheck(argv);
	getSettings(argc, argv, instance);

	getcwd(cwd, PATH_MAX);
	findAll(numFiles, cwd);

	std::vector<std::string> *filePaths = new std::vector<std::string>();

	getPaths(filePaths, cwd, "");
	compression(filePaths);

	delete(instance);
	delete(numFiles);
	delete(filePaths);
	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <streambuf>

#include <3pp/mpc/mpc.h>

std::string readFile(char *fname)
{
    std::ifstream is(fname, std::ifstream::in);
    std::string str(
        (std::istreambuf_iterator<char>(is)),
        std::istreambuf_iterator<char>()
    );
    return str + '\n';
}

int main(int argc, char **argv)
{
    if (argc <= 1) {
        std::cout << "Usage: " << argv[0] << "file\n";
        return 1;
    }
    mpc_parser_t* Comment   = mpc_new("comment");
    mpc_parser_t* Indent   = mpc_new("indent");
    mpc_parser_t* Newline   = mpc_new("newline");
    mpc_parser_t* WhiteSpace = mpc_new("ws");
    mpc_parser_t* OptionalWhiteSpace = mpc_new("ows");
    mpc_parser_t* OptionalWhiteSpaceNewline = mpc_new("owsn");
    mpc_parser_t* Number   = mpc_new("number");
    mpc_parser_t* Comparator = mpc_new("comparator");
    mpc_parser_t* BinaryOp = mpc_new("binaryop");
    mpc_parser_t* FactorOperator = mpc_new("factorop");
    mpc_parser_t* TermOperator = mpc_new("termop");
    mpc_parser_t* Expr     = mpc_new("expr");
    mpc_parser_t* Body     = mpc_new("body");
    mpc_parser_t* Identifier = mpc_new("identifier");
    mpc_parser_t* TypeIdent = mpc_new("typeident");
    mpc_parser_t* Import = mpc_new("import");
    mpc_parser_t* MethodRet = mpc_new("methodret");
    mpc_parser_t* MethodDef = mpc_new("methoddef");
    mpc_parser_t* ParamDef = mpc_new("paramdef");
    mpc_parser_t* String = mpc_new("string");
    mpc_parser_t* Args = mpc_new("args");
    mpc_parser_t* Lexp = mpc_new("lexp");
    mpc_parser_t* Factor = mpc_new("factor");
    mpc_parser_t* Lambda = mpc_new("lambda");
    mpc_parser_t* MethodCall = mpc_new("methodcall");
    mpc_parser_t* MapIndex = mpc_new("mapindex");
    mpc_parser_t* ListItem = mpc_new("listitem");
    mpc_parser_t* MapItem = mpc_new("mapitem");
    mpc_parser_t* TupleMap = mpc_new("tuplemap");
    mpc_parser_t* MapItems = mpc_new("mapitems");
    mpc_parser_t* ListItems = mpc_new("listitems");
    mpc_parser_t* List = mpc_new("list");
    mpc_parser_t* Namespacedef = mpc_new("namespacedef");
    mpc_parser_t* Primitive = mpc_new("primitive");
    mpc_parser_t* Range = mpc_new("range");
    mpc_parser_t* MatchCond = mpc_new("matchcond");
    mpc_parser_t* MatchCase = mpc_new("matchcase");
    mpc_parser_t* Match = mpc_new("match");
    mpc_parser_t* If = mpc_new("if");
    mpc_parser_t* Assignment = mpc_new("assignment");
    mpc_parser_t* Par = mpc_new("par");
    mpc_parser_t* Stmt = mpc_new("stmt");
    mpc_parser_t* Term = mpc_new("term");
    mpc_parser_t* Const = mpc_new("const");
    mpc_parser_t* Return = mpc_new("return");
    mpc_parser_t* Pure = mpc_new("pure");
    mpc_parser_t* TopLevel = mpc_new("toplevel");
    mpc_parser_t* NolangPure = mpc_new("nolangpure");

    mpc_err_t* err = mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE,
        "comment    : /(#|\\/\\/)[^\\r\\n]*/"
        "           | /\\/\\*[^\\*]*(\\*[^\\/][^\\*]*)*\\*\\// ;"
        "indent     : /\\s\\s+/ ;"
        "newline    : '\\n';"
        "ws         : /[\\s]+/ ;"
        "ows        : /[\\s\\t]*/ ;"
        "owsn       : /[\\s\\t\\n]*/ ;"
        "identifier : /[A-Za-z_][A-Za-z0-9_-]*/ ;"
        "typeident  : <identifier> <ows> ':' <ows> <identifier> ;"
        "number     : /[0-9]+/ ;"
        "string     : /\"(\\\\.|[^\"])*\"/ "
        "           | /\'(\\\\.|[^\'])*\'/ ; "
        "comparator : \">=\""
        "           | \"<=\""
        "           | '>'"
        "           | '<'"
        "           | \"==\""
        "           | \"!=\";"
        "binaryop   : \"&&\""
        "           | \"||\""
        "           ;"
        "factorop   : '*'"
        "           | '/'"
        "           | \"div\""
        "           | \"mod\""
        "           | \"rem\";"
        "termop     : '+'"
        "           | '-';"
        "import     : \"import\" <ws> <namespacedef> (<ws> \"as\" <ws> <identifier>)?  <newline>;"
        "const      : \"const\" <ws> <assignment> <newline>;"
        "methodret  : <ows> ':' <ows> <identifier> ;"
        "methoddef  : (<pure> <ws>)? <identifier> <ows> <args>? <methodret>? <ows> \"=>\" (<newline>|<ws>) <body> ;"
        "paramdef   : <typeident>? <ows> (',' <ows> <typeident>)*; "
        "args       : '(' <paramdef>? ')'; "
        "factor     : <par>"
        "           | <namespacedef>"
        "           | '(' <lexp> ')'"
        "           | <number>"
        "           | <string>"
        "           | <identifier>; "
        "term       : <factor> (<ows> <factorop> <ows> <factor>)*;"
        "lexp       : <term> (<ows> (<termop> | <comparator>) <ows> <term>)* ; "
        "expr       : <list>"
        "           | <lambda>"
        "           | <lexp> (<ows> <binaryop> <ows> <lexp>)*;"
        "lambda     : '(' <ows> <paramdef> <ows> \"=>\" ((<newline> <body>) | (<ows> <stmt>)) <ows> ')' ;"
        "methodcall : '(' (<expr> (',' <ows> <expr>)*)? ')';"
        "mapindex   : '[' <expr> ']';"
        "listitem   : <expr>;"
        "mapitem    : <string> <ows> ':' <owsn> <expr> ;"
        "tuplemap   : '(' <string> <owsn> ',' <owsn> <lexp> ')';"
        "mapitems   : (<tuplemap> | <mapitem>) <owsn> (',' <owsn> (<tuplemap> | <mapitem>)) *;"
        "listitems  : <listitem> (<owsn> ',' <owsn> <listitem>) *;"
        "list       : '[' <owsn> (<mapitems> | <listitems>)? <owsn> ']' ;"
        "namespacedef : <identifier> ('.' <identifier>)* (<methodcall> | <mapindex>)?;"
        "primitive  : <identifier> | <number> | <string> ;"
        "range      : <primitive> \"..\" <primitive>?;"
        "assignment : (<typeident>|<namespacedef>) <ws> '=' <ws> <expr>;"
        "matchcond  : <range> | ((<comparator> <ows>)? <primitive>) | '?';"
        "matchcase  : <comment> | (<indent> <matchcond> <ows> ':' <ows> <stmt> <newline>);"
        "match      : \"match\" <ws> <stmt> <ows> \"=>\" <newline> <matchcase>+;"
        "if         : \"if\" <ws> <stmt>"
        "             <ows> \"then\" <ws> <stmt>+"
        "             (<ows> \"else\" <ws> <stmt>+)?;"
        "par        : \"par\" <ws> <stmt>;"
        "stmt       : <match>"
        "           | <if>"
        "           | <return>"
        "           | <assignment>"
        "           | <expr>"
        "           | <namespacedef>"
        "           | <list>"
        "           | <comment>;"
        "body       : ((<indent>+ <stmt>)? <newline>)* ;"
        "pure       : \"pure\" | \"side\" ;"
        "return     : \"return\" <ws> <stmt> (<ows> ',' <ows> <stmt>)*;"
        "toplevel   : <import>"
        "           | <const>"
        "           | <comment>"
        "           | <methoddef>"
        "           | <newline>;"
        "nolangpure : /^/ <toplevel>* /$/;"
      ,
        Comment, Indent, Newline,
        WhiteSpace, OptionalWhiteSpace, OptionalWhiteSpaceNewline,
        Identifier, TypeIdent,
        Number, String,
        Comparator, BinaryOp, FactorOperator, TermOperator,
        Import, Const,
        MethodRet, MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, Lambda, MethodCall,
        MapIndex, ListItem, MapItem, TupleMap, MapItems, ListItems, List,
        Namespacedef,
        Primitive, Range,
        Assignment,
        MatchCond, MatchCase, Match,
        If, Par,
        Stmt,
        Body, Pure, Return,
        TopLevel, NolangPure, NULL);

    if (err != NULL) {
        mpc_err_print(err);
        mpc_err_delete(err);
        exit(1);
    }

    mpc_result_t r;
    std::string data = readFile(argv[1]);
    int res = 0;
    if (mpc_parse(argv[1], data.c_str(), NolangPure, &r)) {
      mpc_ast_print(static_cast<mpc_ast_t*>(r.output));
      mpc_ast_delete(static_cast<mpc_ast_t*>(r.output));
    } else {
        mpc_err_print(r.error);
        mpc_err_delete(r.error);
        res = 1;
    }

    mpc_cleanup(39,
        Comment, Indent, Newline,
        WhiteSpace, OptionalWhiteSpace, OptionalWhiteSpaceNewline,
        Identifier, TypeIdent,
        Number, String,
        Comparator, BinaryOp, FactorOperator, TermOperator,
        Import, Const,
        MethodRet, MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, Lambda, MethodCall,
        MapIndex, ListItem, MapItem, TupleMap, MapItems, ListItems, List,
        Namespacedef,
        Primitive, Range,
        Assignment,
        MatchCond, MatchCase, Match,
        If, Par,
        Stmt,
        Body, Pure, Return,
        TopLevel, NolangPure);

    return res;
}
<commit_msg>Endmatch as a hack for now<commit_after>#include <iostream>
#include <fstream>
#include <streambuf>

#include <3pp/mpc/mpc.h>

std::string readFile(char *fname)
{
    std::ifstream is(fname, std::ifstream::in);
    std::string str(
        (std::istreambuf_iterator<char>(is)),
        std::istreambuf_iterator<char>()
    );
    return str + '\n';
}

int main(int argc, char **argv)
{
    if (argc <= 1) {
        std::cout << "Usage: " << argv[0] << "file\n";
        return 1;
    }
    mpc_parser_t* Comment   = mpc_new("comment");
    mpc_parser_t* Indent   = mpc_new("indent");
    mpc_parser_t* Newline   = mpc_new("newline");
    mpc_parser_t* WhiteSpace = mpc_new("ws");
    mpc_parser_t* OptionalWhiteSpace = mpc_new("ows");
    mpc_parser_t* OptionalWhiteSpaceNewline = mpc_new("owsn");
    mpc_parser_t* Number   = mpc_new("number");
    mpc_parser_t* Comparator = mpc_new("comparator");
    mpc_parser_t* BinaryOp = mpc_new("binaryop");
    mpc_parser_t* FactorOperator = mpc_new("factorop");
    mpc_parser_t* TermOperator = mpc_new("termop");
    mpc_parser_t* Expr     = mpc_new("expr");
    mpc_parser_t* Body     = mpc_new("body");
    mpc_parser_t* Identifier = mpc_new("identifier");
    mpc_parser_t* TypeIdent = mpc_new("typeident");
    mpc_parser_t* Import = mpc_new("import");
    mpc_parser_t* MethodRet = mpc_new("methodret");
    mpc_parser_t* MethodDef = mpc_new("methoddef");
    mpc_parser_t* ParamDef = mpc_new("paramdef");
    mpc_parser_t* String = mpc_new("string");
    mpc_parser_t* Args = mpc_new("args");
    mpc_parser_t* Lexp = mpc_new("lexp");
    mpc_parser_t* Factor = mpc_new("factor");
    mpc_parser_t* Lambda = mpc_new("lambda");
    mpc_parser_t* MethodCall = mpc_new("methodcall");
    mpc_parser_t* MapIndex = mpc_new("mapindex");
    mpc_parser_t* ListItem = mpc_new("listitem");
    mpc_parser_t* MapItem = mpc_new("mapitem");
    mpc_parser_t* TupleMap = mpc_new("tuplemap");
    mpc_parser_t* MapItems = mpc_new("mapitems");
    mpc_parser_t* ListItems = mpc_new("listitems");
    mpc_parser_t* List = mpc_new("list");
    mpc_parser_t* Namespacedef = mpc_new("namespacedef");
    mpc_parser_t* Primitive = mpc_new("primitive");
    mpc_parser_t* Range = mpc_new("range");
    mpc_parser_t* MatchCond = mpc_new("matchcond");
    mpc_parser_t* MatchCase = mpc_new("matchcase");
    mpc_parser_t* Match = mpc_new("match");
    mpc_parser_t* If = mpc_new("if");
    mpc_parser_t* Assignment = mpc_new("assignment");
    mpc_parser_t* Par = mpc_new("par");
    mpc_parser_t* Stmt = mpc_new("stmt");
    mpc_parser_t* Term = mpc_new("term");
    mpc_parser_t* Const = mpc_new("const");
    mpc_parser_t* Return = mpc_new("return");
    mpc_parser_t* Pure = mpc_new("pure");
    mpc_parser_t* TopLevel = mpc_new("toplevel");
    mpc_parser_t* NolangPure = mpc_new("nolangpure");

    mpc_err_t* err = mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE,
        "comment    : /(#|\\/\\/)[^\\r\\n]*/"
        "           | /\\/\\*[^\\*]*(\\*[^\\/][^\\*]*)*\\*\\// ;"
        "indent     : /\\s\\s+/ ;"
        "newline    : '\\n';"
        "ws         : /[\\s]+/ ;"
        "ows        : /[\\s\\t]*/ ;"
        "owsn       : /[\\s\\t\\n]*/ ;"
        "identifier : /[A-Za-z_][A-Za-z0-9_-]*/ ;"
        "typeident  : <identifier> <ows> ':' <ows> <identifier> ;"
        "number     : /[0-9]+/ ;"
        "string     : /\"(\\\\.|[^\"])*\"/ "
        "           | /\'(\\\\.|[^\'])*\'/ ; "
        "comparator : \">=\""
        "           | \"<=\""
        "           | '>'"
        "           | '<'"
        "           | \"==\""
        "           | \"!=\";"
        "binaryop   : \"&&\""
        "           | \"||\""
        "           ;"
        "factorop   : '*'"
        "           | '/'"
        "           | \"div\""
        "           | \"mod\""
        "           | \"rem\";"
        "termop     : '+'"
        "           | '-';"
        "import     : \"import\" <ws> <namespacedef> (<ws> \"as\" <ws> <identifier>)?  <newline>;"
        "const      : \"const\" <ws> <assignment> <newline>;"
        "methodret  : <ows> ':' <ows> <identifier> ;"
        "methoddef  : (<pure> <ws>)? <identifier> <ows> <args>? <methodret>? <ows> \"=>\" (<newline>|<ws>) <body> ;"
        "paramdef   : <typeident>? <ows> (',' <ows> <typeident>)*; "
        "args       : '(' <paramdef>? ')'; "
        "factor     : <par>"
        "           | <namespacedef>"
        "           | '(' <lexp> ')'"
        "           | <number>"
        "           | <string>"
        "           | <identifier>; "
        "term       : <factor> (<ows> <factorop> <ows> <factor>)*;"
        "lexp       : <term> (<ows> (<termop> | <comparator>) <ows> <term>)* ; "
        "expr       : <list>"
        "           | <lambda>"
        "           | <lexp> (<ows> <binaryop> <ows> <lexp>)*;"
        "lambda     : '(' <ows> <paramdef> <ows> \"=>\" ((<newline> <body>) | (<ows> <stmt>)) <ows> ')' ;"
        "methodcall : '(' (<stmt> (',' <ows> <stmt>)*)? ')';"
        "mapindex   : '[' <expr> ']';"
        "listitem   : <expr>;"
        "mapitem    : <string> <ows> ':' <owsn> <expr> ;"
        "tuplemap   : '(' <string> <owsn> ',' <owsn> <lexp> ')';"
        "mapitems   : (<tuplemap> | <mapitem>) <owsn> (',' <owsn> (<tuplemap> | <mapitem>)) *;"
        "listitems  : <listitem> (<owsn> ',' <owsn> <listitem>) *;"
        "list       : '[' <owsn> (<mapitems> | <listitems>)? <owsn> ']' ;"
        "namespacedef : <identifier> ('.' <identifier>)* (<methodcall> | <mapindex>)?;"
        "primitive  : <identifier> | <number> | <string> ;"
        "range      : <primitive> \"..\" <primitive>?;"
        "assignment : (<typeident>|<namespacedef>) <ws> '=' <ws> <expr>;"
        "matchcond  : <range> | ((<comparator> <ows>)? <primitive>) | '?';"
        "matchcase  : <comment> | (<indent> <matchcond> <ows> ':' <ows> <stmt> <newline>);"
        "match      : \"match\" <ws> <stmt> <ows> \"=>\" <newline> <matchcase>+ (<indent> \"endmatch\")?;"
        "if         : \"if\" <ws> <stmt>"
        "             <ows> \"then\" <ws> <stmt>+"
        "             (<ows> \"else\" <ws> <stmt>+)?;"
        "par        : \"par\" <ws> <stmt>;"
        "stmt       : <match>"
        "           | <if>"
        "           | <return>"
        "           | <assignment>"
        "           | <expr>"
        "           | <namespacedef>"
        "           | <list>"
        "           | <comment>;"
        "body       : ((<indent>+ <stmt>)? <newline>)* ;"
        "pure       : \"pure\" | \"side\" ;"
        "return     : \"return\" <ws> <stmt> (<ows> ',' <ows> <stmt>)*;"
        "toplevel   : <import>"
        "           | <const>"
        "           | <comment>"
        "           | <methoddef>"
        "           | <newline>;"
        "nolangpure : /^/ <toplevel>* /$/;"
      ,
        Comment, Indent, Newline,
        WhiteSpace, OptionalWhiteSpace, OptionalWhiteSpaceNewline,
        Identifier, TypeIdent,
        Number, String,
        Comparator, BinaryOp, FactorOperator, TermOperator,
        Import, Const,
        MethodRet, MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, Lambda, MethodCall,
        MapIndex, ListItem, MapItem, TupleMap, MapItems, ListItems, List,
        Namespacedef,
        Primitive, Range,
        Assignment,
        MatchCond, MatchCase, Match,
        If, Par,
        Stmt,
        Body, Pure, Return,
        TopLevel, NolangPure, NULL);

    if (err != NULL) {
        mpc_err_print(err);
        mpc_err_delete(err);
        exit(1);
    }

    mpc_result_t r;
    std::string data = readFile(argv[1]);
    int res = 0;
    if (mpc_parse(argv[1], data.c_str(), NolangPure, &r)) {
      mpc_ast_print(static_cast<mpc_ast_t*>(r.output));
      mpc_ast_delete(static_cast<mpc_ast_t*>(r.output));
    } else {
        mpc_err_print(r.error);
        mpc_err_delete(r.error);
        res = 1;
    }

    mpc_cleanup(39,
        Comment, Indent, Newline,
        WhiteSpace, OptionalWhiteSpace, OptionalWhiteSpaceNewline,
        Identifier, TypeIdent,
        Number, String,
        Comparator, BinaryOp, FactorOperator, TermOperator,
        Import, Const,
        MethodRet, MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, Lambda, MethodCall,
        MapIndex, ListItem, MapItem, TupleMap, MapItems, ListItems, List,
        Namespacedef,
        Primitive, Range,
        Assignment,
        MatchCond, MatchCase, Match,
        If, Par,
        Stmt,
        Body, Pure, Return,
        TopLevel, NolangPure);

    return res;
}
<|endoftext|>