Ejemplo n.º 1
0
function CreateView($args, $targs)
{
    grokit_assert(\count($args) == 1, 'CreateView supports exactly 1 input');
    $type = $args[0];
    grokit_assert($type->is('array'), 'CreateView cannot create view on non-array type');
    $innerType = $type->get('type');
    $size = $type->get('size');
    $viewType = lookupType('BASE::FixedArrayView', ['type' => $innerType, 'size' => $size]);
    $funcname = generate_name('CreateView_');
    ?>

<?php 
    echo $viewType;
    ?>
 <?php 
    echo $funcname;
    ?>
( const <?php 
    echo $type;
    ?>
 &array ) {
	return <?php 
    echo $viewType;
    ?>
(array.data());
}

<?php 
    return ['kind' => 'FUNCTION', 'name' => $funcname, 'input' => $args, 'result' => $viewType, 'deterministic' => false];
}
Ejemplo n.º 2
0
function Hash($args, array $t_args = [])
{
    $funcName = generate_name('Hash_');
    $retType = lookupType('base::BIGINT');
    echo $retType;
    ?>
 <?php 
    echo $funcName;
    ?>
( <?php 
    echo const_typed_ref_args($args);
    ?>
 ) {
    uint64_t hashVal = H_b;
<?php 
    foreach ($args as $name => $type) {
        ?>
    hashVal = CongruentHash(<?php 
        echo $name;
        ?>
, hashVal);
<?php 
    }
    // foreach argument
    ?>
    return static_cast<<?php 
    echo $retType;
    ?>
>(hashVal);
}
<?php 
    return ['kind' => 'FUNCTION', 'name' => $funcName, 'result' => $retType, 'system_headers' => ['cinttypes'], 'user_headers' => ['HashFunctions.h'], 'deterministic' => true];
}
Ejemplo n.º 3
0
 public function sendpic()
 {
     //if (empty($file['tmp_name'])) return false;
     function reArrayFiles(&$file_post)
     {
         $file_ary = array();
         $file_count = count($file_post['name']);
         $file_keys = array_keys($file_post);
         for ($i = 0; $i < $file_count; $i++) {
             foreach ($file_keys as $key) {
                 $file_ary[$i][$key] = $file_post[$key][$i];
             }
         }
         return $file_ary;
     }
     function generate_name()
     {
         $number = '12';
         $arr = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'v', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0');
         // Генерируем пароль
         $pass = "";
         for ($i = 0; $i < $number; $i++) {
             // Вычисляем случайный индекс массива
             $index = rand(0, count($arr) - 1);
             $pass .= $arr[$index];
         }
         return $pass;
     }
     $file_ary = reArrayFiles($_FILES['userfile']);
     foreach ($file_ary as $file) {
         $imageinfo = getimagesize($file['tmp_name']);
         $file['name'] = generate_name() . '.jpg';
         //print_r($file['tmp_name']);
         //print_r($imageinfo);
         //die;
         if ($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {
             echo "Sorry, we only accept GIF and JPEG images\n";
             exit;
         }
         $uploaddir = 'uploads/';
         $uploadfile = $uploaddir . basename($file['name']);
         if (move_uploaded_file($file['tmp_name'], $uploadfile)) {
             echo "File is valid, and was successfully uploaded.\n";
         } else {
             echo "File uploading failed.\n";
         }
         $data = array();
         $data['userId'] = session::get('userId');
         $data['path'] = URL . $uploadfile;
         $data['name'] = $uploadfile;
         $data['postid'] = session::get('postId');
         $this->model->addpic($data);
     }
 }
Ejemplo n.º 4
0
/**
 * Handles the uploading and db entry for a file
 *
 * @param  UploadedFile $file
 * @return array
 */
function upload_file($file)
{
    global $db;
    // Handle file errors
    if ($file->error) {
        throw new UploadException($file->error);
    }
    // Check if a file with the same hash and size (a file which is the same) does already exist in
    // the database; if it does, delete the file just uploaded and return the proper link and data.
    $q = $db->prepare('SELECT filename, COUNT(*) AS count FROM files WHERE hash = (:hash) ' . 'AND size = (:size)');
    $q->bindValue(':hash', $file->get_sha1(), PDO::PARAM_STR);
    $q->bindValue(':size', $file->size, PDO::PARAM_INT);
    $q->execute();
    $result = $q->fetch();
    if ($result['count'] > 0) {
        unlink($file->tempfile);
        return array('hash' => $file->get_sha1(), 'name' => $file->name, 'url' => POMF_URL . $result['filename'], 'size' => $file->size);
    }
    // Generate a name for the file
    $newname = generate_name($file);
    // Attempt to move it to the static directory
    if (move_uploaded_file($file->tempfile, POMF_FILES_ROOT . $newname)) {
        // Need to change permissions for the new file to make it world readable
        if (chmod(POMF_FILES_ROOT . $newname, 0644)) {
            // Add it to the database
            if (empty($_SESSION['id'])) {
                // Query if user is NOT logged in
                $q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, ' . 'expire, delid) VALUES (:hash, :orig, :name, :size, :date, ' . ':exp, :del)');
            } else {
                // Query if user is logged in (insert user id together with other data)
                $q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, ' . 'expire, delid, user) VALUES (:hash, :orig, :name, :size, ' . ':date, :expires, :delid, :user)');
                $q->bindValue(':user', $_SESSION['id'], PDO::PARAM_INT);
            }
            // Common parameters binding
            $q->bindValue(':hash', $file->get_sha1(), PDO::PARAM_STR);
            $q->bindValue(':orig', strip_tags($file->name), PDO::PARAM_STR);
            $q->bindValue(':name', $newname, PDO::PARAM_STR);
            $q->bindValue(':size', $file->size, PDO::PARAM_INT);
            $q->bindValue(':date', date('Y-m-d'), PDO::PARAM_STR);
            $q->bindValue(':exp', null, PDO::PARAM_STR);
            $q->bindValue(':del', sha1($file->tempfile), PDO::PARAM_STR);
            $q->execute();
            return array('hash' => $file->get_sha1(), 'name' => $file->name, 'url' => POMF_URL . $newname, 'size' => $file->size);
        } else {
            throw new Exception('Failed to change file permissions', 500);
        }
    } else {
        throw new Exception('Failed to move file to destination', 500);
    }
}
Ejemplo n.º 5
0
function PatternMatcherOnig($t_args, $inputs)
{
    grokit_assert(\count($inputs) == 1, 'PatternMatcherOnig GF only supports 1 input!');
    $pattern = get_first_key($t_args, ['pattern']);
    $inName = array_keys($inputs)[0];
    $inType = array_get_index($inputs, 0);
    $inTypeString = $inType->name();
    $validTypes = ['BASE::STRING_LITERAL'];
    grokit_assert(in_array($inTypeString, $validTypes), 'Unsupported input type ' . $inTypeString);
    $className = generate_name('PatternMatcherOnigGF');
    ?>

class <?php 
    echo $className;
    ?>
 {

    PatternMatcherOnig matcher;

public:
    <?php 
    echo $className;
    ?>
() :
        matcher("<?php 
    echo $pattern;
    ?>
")
    { }

    bool Filter( const <?php 
    echo $inType;
    ?>
 & <?php 
    echo $inName;
    ?>
 ) {
        return matcher.Match(<?php 
    echo $inName;
    ?>
);
    }
};

<?php 
    return ['kind' => 'GF', 'name' => $className, 'input' => $inputs, 'user_headers' => ['PatternMatcherOnig.h']];
}
Ejemplo n.º 6
0
function SplitState(array $t_args)
{
    $sys_headers = ['mutex', 'condition_variable', 'array', 'random'];
    $user_headers = [];
    grokit_assert(array_key_exists('type', $t_args), 'SplitState: No type given');
    grokit_assert(array_key_exists('size', $t_args), 'SplitState: No size given');
    $type = $t_args['type'];
    $size = $t_args['size'];
    $className = generate_name('SplitState_');
    ?>
class <?php 
    echo $className;
    ?>
 {
public:
    using StateType = <?php 
    echo $type;
    ?>
;

    static constexpr size_t NUM_STATES = <?php 
    echo $size;
    ?>
;
private:
    using UniqueLock =  std::unique_lock<std::mutex>;

    using StateArray = std::array<StateType *, NUM_STATES>;
    using BoolArray = std::array<bool, NUM_STATES>;

    // Array of states
    StateArray stateArray;

    // Mutex to protect states
    std::mutex myMutex;

    // Condition variable to wake up threads blocked on acquiring a state.
    std::condition_variable signalVar;

    // Keeps track of which states are available to be checked out.
    BoolArray writeLocked;

    // Random number generator
    std::mt19937_64 rng;

public:

    // Constructor
    <?php 
    echo $className;
    ?>
( ) :
        stateArray(),
        myMutex(),
        signalVar(),
        writeLocked(),
        rng()
    {
        stateArray.fill(nullptr);
        writeLocked.fill(false);

        std::random_device rd;

        // 64-bits of seed
        uint32_t seed_vals[2];
        seed_vals[0] = rd();
        seed_vals[1] = rd();

        std::seed_seq seed(seed_vals, seed_vals + 2);

        rng.seed(seed);
    }

    // Destructor
    ~<?php 
    echo $className;
    ?>
() {
        for( auto elem : stateArray ) {
            if( elem != nullptr ) {
                delete elem;
            }
        }
    }

    // Methods

    int CheckOutOne( int *theseAreOK, StateType *& checkMeOut ) {
        // first, figure out all of the OK segments
        int numWanted = 0;
        int goodOnes[NUM_STATES];
        for (int i = 0; i < NUM_STATES; i++) { //>
            if (theseAreOK[i] == 1) {
                goodOnes[numWanted] = i;
                numWanted++;
            }
        }

        {   UniqueLock lock(myMutex); // Acquire lock

            // now, try them one-at-a-time, in random order
            while (1) {

                // try each of the desired hash table segments, in random order
                for (int i = 0; i < numWanted; i++) { //>

                    // randomly pick one of the guys in the list
                    std::uniform_int_distribution<int> dist(i, numWanted-1);
                    int whichIndex = dist(rng);

                    // move him into the current slot
                    int whichToChoose = goodOnes[whichIndex];
                    goodOnes[whichIndex] = goodOnes[i];
                    goodOnes[i] = whichToChoose;

                    // try him
                    if (!writeLocked[whichToChoose]) {

                        // he is open, so write lock him
                        writeLocked[whichToChoose] = true;

                        // and return him
                        checkMeOut = stateArray[whichToChoose];
                        stateArray[whichToChoose] = nullptr;
                        return whichToChoose;
                    }
                }

                // if we got here, then every one that we want is write locked.  So
                // we will go to sleep until one of them is unlocked, at which point
                // we will wake up and try again...
                signalVar.wait(lock);
            }
        }
    }

    void CheckIn( int whichEntry, StateType *& checkMeIn ) {
        // just note that no one is writing this one, then signal all potential writers
        {
            UniqueLock lock(myMutex);
            writeLocked[whichEntry] = false;

            stateArray[whichEntry] = checkMeIn;
            checkMeIn = nullptr;
        }

        signalVar.notify_all();
    }

    StateType * Peek( int whichEntry ) {
        return stateArray[ whichEntry ];
    }

    void Delete( int whichEntry ) {
        if( stateArray[whichEntry] != nullptr ) {

            delete stateArray[whichEntry];
            stateArray[whichEntry] = nullptr;
        }
    }

    void Reset() {
        for(size_t i = 0; i < NUM_STATES; i++) {
<?php 
    if ($type->is('resettable')) {
        ?>
            if( stateArray[i] != nullptr ) {
                stateArray[i]->Reset();        
            }
<?php 
    } else {
        ?>
            Delete(i);
<?php 
    }
    // not resettabile
    ?>
        }
    }
};
<?php 
    return ['kind' => 'RESOURCE', 'name' => $className, 'system_headers' => $sys_headers, 'user_headers' => $user_headers];
}
Ejemplo n.º 7
0
/**
 * Handles the uploading and db entry for a file.
 *
 * @param UploadedFile $file
 *
 * @return array
 */
function upload_file($file)
{
    global $db;
    // Handle file errors
    if ($file->error) {
        throw new UploadException($file->error);
    }
    // Check if a file with the same hash and size (a file which is the same) does already exist in
    // the database; if it does, delete the file just uploaded and return the proper link and data.
    $q = $db->prepare('SELECT filename, COUNT(*) AS count FROM files WHERE hash = (:hash) ' . 'AND size = (:size)');
    $q->bindValue(':hash', $file->get_sha1(), PDO::PARAM_STR);
    $q->bindValue(':size', $file->size, PDO::PARAM_INT);
    $q->execute();
    $result = $q->fetch();
    if ($result['count'] > 0) {
        unlink($file->tempfile);
        return array('hash' => $file->get_sha1(), 'name' => $file->name, 'url' => POMF_URL . $result['filename'], 'size' => $file->size);
    }
    // Generate a name for the file
    $newname = generate_name($file);
    // Attempt to move it to the static directory
    if (move_uploaded_file($file->tempfile, POMF_FILES_ROOT . $newname)) {
        // Need to change permissions for the new file to make it world readable
        if (chmod(POMF_FILES_ROOT . $newname, 0644)) {
            // Add it to the database
            $q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, ' . 'expire, delid) VALUES (:hash, :orig, :name, :size, :date, ' . ':exp, :del)');
            //Adds expire date to database for removal via python script and cron
            $expTime = date("Y-m-d H:i:s", time() + 9001 * 60 * 60);
            if ($_POST['Time'] == '1') {
                $expTime = date("Y-m-d H:i:s", time() + 9001 * 60 * 60);
            }
            if ($_POST['Time'] == '2') {
                $expTime = date("Y-m-d H:i:s", time() + 6 * 60 * 60);
            }
            if ($_POST['Time'] == '3') {
                $expTime = date("Y-m-d H:i:s", time() + 24 * 60 * 60);
            }
            if ($_POST['Time'] == '4') {
                $expTime = date("Y-m-d H:i:s", time() + 48 * 60 * 60);
            }
            if ($_POST['Time'] == '5') {
                $expTime = date("Y-m-d H:i:s", time() + 168 * 60 * 60);
            }
            if ($_POST['Time'] == '6') {
                $expTime = date("Y-m-d H:i:s", time() + 720 * 60 * 60);
            }
            // Common parameters binding
            $q->bindValue(':hash', $file->get_sha1(), PDO::PARAM_STR);
            $q->bindValue(':orig', strip_tags($file->name), PDO::PARAM_STR);
            $q->bindValue(':name', $newname, PDO::PARAM_STR);
            $q->bindValue(':size', $file->size, PDO::PARAM_INT);
            $q->bindValue(':date', date('Y-m-d'), PDO::PARAM_STR);
            $q->bindValue(':exp', $expTime, PDO::PARAM_STR);
            $q->bindValue(':del', sha1($file->tempfile), PDO::PARAM_STR);
            $q->execute();
            return array('hash' => $file->get_sha1(), 'name' => $file->name, 'url' => POMF_URL . $newname, 'size' => $file->size);
        } else {
            throw new Exception('Failed to change file permissions', 500);
        }
    } else {
        throw new Exception('Failed to move file to destination', 500);
    }
}
Ejemplo n.º 8
0
/**
 *  GI that generates data in clusters, using a specified distribution for each
 *  cluster.
 *
 *  This GI requires the following template arguments:
 *      - 'n' or 0
 *          The number of tuples to generate. Note: this value is per task.
 *          The total number of tuples generated will be n_tasks * n
 *      - 'centers' or 1
 *          A list of configuration for the centers.
 *
 *  The following template arguments are optional:
 *      - 'outputs'
 *          If the outputs of the GI are not given implicitly, they can be
 *          specified in this template argument. The number of dimensions will
 *          be determined by the number of outputs.
 *
 *          All output types must be numeric real types. The default type for
 *          outputs is DOUBLE.
 *      - 'dist.lib' = 'std'
 *          Which library to use for generating distributions.
 *          Valid options are:
 *              - std
 *              - boost
 *      - 'seed' = null
 *          The seed to be used for the random number generator. This seed will
 *          be used to generate the seed for each task, and different runs with
 *          the same seed will produce the same data.
 *      - 'compute.sets' = 1
 *          The number of sets of tuples to compute at once.
 *
 *  Each center configuration is a functor with the form:
 *      dist_name(args)
 *
 *  The following distributions are supported:
 *      { Uniform Distributions }
 *      - uniform(a = 0, b = 1)
 *
 *      { Normal Distributions }
 *      - normal(mean = 0.0, std_dev = 1.0) [ synonyms: gaussian ]
 *      - inverse_gaussian(mean = 1, shape = 1) [ synonyms: inverse_normal ]
 *
 *      { Bernoulli Distributions }
 *      - binomial(t = 1, p = 0.5)
 *      - negative_binomial(k = 1, p = 0.5)
 *
 *      { Poisson Distributions }
 *      - exponential( lambda = 1 )
 *      - gamma(alpha = 1, beta = 1)    [ synonyms: Gamma ]
 */
function ClusterGen(array $t_args, array $outputs)
{
    $sys_headers = ['array', 'cinttypes'];
    $user_headers = [];
    $libraries = [];
    if (\count($outputs) == 0) {
        grokit_assert(array_key_exists('outputs', $t_args), 'ClusterGen: No outputs specified');
        $count = 0;
        foreach ($t_args['outputs'] as $type) {
            if (is_identifier($type)) {
                $type = lookupType($type);
            }
            grokit_assert(is_datatype($type), 'ClusterGen: Non data-type ' . $type . ' given as output');
            $name = 'output' . $count++;
            $outputs[$name] = $type;
        }
    }
    foreach ($outputs as $name => &$type) {
        if (is_null($type)) {
            $type = lookupType('base::DOUBLE');
        } else {
            grokit_assert($type->is('real'), 'ClusterGen: Non-real datatype ' . $type . ' given as output');
        }
    }
    $myOutputs = [];
    foreach ($outputs as $name => $type) {
        $myOutputs[$name] = $type;
    }
    $tSize = \count($outputs);
    $seed = get_default($t_args, 'seed', null);
    if ($seed !== null) {
        grokit_assert(is_int($seed), 'ClusterGen: Seed must be an integer or null.');
    } else {
        $user_headers[] = 'HashFunctions.h';
    }
    $distLib = get_default($t_args, 'dist.lib', 'std');
    $distNS = '';
    switch ($distLib) {
        case 'std':
            $sys_headers[] = 'random';
            $distNS = 'std';
            break;
        case 'boost':
            $sys_headers[] = 'boost/random.hpp';
            $distNS = 'boost::random';
            $libraries[] = 'boost_random-mt';
            if ($seed === null) {
                // Need random_device
                $sys_headers[] = 'boost/random/random_device.hpp';
                $libraries[] = 'boost_system-mt';
            }
            break;
        default:
            grokit_error('ClusterGen: Unknown RNG library ' . $distLib);
    }
    $distRNG = 'mt19937';
    $RNGtype = $distNS . '::' . $distRNG;
    $nTuples = get_first_key($t_args, ['n', '0']);
    grokit_assert(is_int($nTuples), 'ClusterGen: the number of tuples to be produced must be an integer.');
    $centers = get_first_key($t_args, ['centers', 1]);
    grokit_assert(is_array($centers), 'ClusterGen: centers must be an array of functors');
    $handleDist = function ($name, $args, $oType) use($distNS) {
        $distName = '';
        $distArgs = [];
        switch ($name) {
            case 'gaussian':
            case 'normal':
                $distName = $distNS . '::' . 'normal_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Normal distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $mean = get_default($args, ['mean', 0], 0.0);
                $sigma = get_default($args, ['std_dev', 'sigma', 1], 1.0);
                grokit_assert(is_numeric($mean), 'ClusterGen: mean parameter of binomial distribution must be a real number.');
                grokit_assert(is_numeric($sigma), 'ClusterGen: sigma parameter of binomial distribution must be a real number.');
                $mean = floatval($mean);
                $sigma = floatval($sigma);
                $distArgs = [$mean, $sigma];
                break;
            case 'binomial':
                $distName = $distNS . '::' . 'binomial_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Binomial distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $t = get_default($args, ['t', 0], 1);
                $p = get_default($args, ['p', 1], 0.5);
                grokit_assert(is_int($t), 'ClusterGen: t parameter of binomial distribution must be an integer.');
                grokit_assert(is_numeric($p), 'ClusterGen: p parameter of binomial distribution must be a real number.');
                $p = floatval($p);
                grokit_assert($p >= 0 && $p <= 1, 'ClusterGen: p parameter of binomial distribution must be in the range [0, 1]');
                grokit_assert($t >= 0, 'ClusterGen: t parameter of binomial distribution must be in the range [0, +inf)');
                $distArgs = [$t, $p];
                break;
            case 'negative_binomial':
                $distName = $distNS . '::' . 'negative_binomial_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Negative Binomial distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $k = get_default($args, ['k', 0], 1);
                $p = get_default($args, ['p', 1], 0.5);
                grokit_assert(is_int($k), 'ClusterGen: k parameter of binomial distribution must be an integer.');
                grokit_assert(is_numeric($p), 'ClusterGen: p parameter of binomial distribution must be a real number.');
                $p = floatval($p);
                grokit_assert($p > 0 && $p <= 1, 'ClusterGen: p parameter of negative binomial distribution must be in the range (0, 1]');
                grokit_assert($k > 0, 'ClusterGen: k parameter of negative binomial distribution must be in the range (0, +inf)');
                $distArgs = [$k, $p];
                break;
            case 'inverse_gaussian':
            case 'inverse_normal':
                grokit_assert(\count($args) <= 2, 'ClusterGen: Inverse Gaussian distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $mean = get_default($args, ['mean', 0], 1);
                $shape = get_default($args, ['shape', 1], 1);
                grokit_assert(is_numeric($mean), 'ClusterGen: mean parameter of inverse gaussian distribution must be a real number.');
                grokit_assert(is_numeric($shape), 'ClusterGen: shape parameter of inverse gaussian distribution must be a real number.');
                $mean = floatval($mean);
                $shape = floatval($shape);
                grokit_assert($mean > 0, 'ClusterGen: mean of inverse gaussian distribution must be in range (0, inf)');
                grokit_assert($shape > 0, 'ClusterGen: shape of inverse gaussian distribution must be in range (0, inf)');
                $gen_args = ['output' => $oType, 'ns' => $distNS];
                $distName = strval(lookupResource('datagen::InverseGaussianGen', $gen_args));
                $distArgs = [$mean, $shape];
                break;
            case 'uniform':
                $distName = $distNS . '::' . 'uniform_real_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Uniform distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $a = get_default($args, ['a', 0], 0.0);
                $b = get_default($args, ['b', 1], 1.0);
                grokit_assert(is_numeric($a), 'ClusterGen: `a` parameter of uniform distribution must be a real number.');
                grokit_assert(is_numeric($b), 'ClusterGen: `b` parameter of uniform distribution must be a real number.');
                $a = floatval($a);
                $b = floatval($b);
                grokit_assert($b >= $a, 'ClusterGen: `b` parameter of uniform distribution must be >= the `a` parameter.');
                $distArgs = [$a, $b];
                break;
            case 'exponential':
                $distName = $distNS . '::' . 'exponential_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 1, 'ClusterGen: Exponential distribution takes at most 1 argument.');
                $lambda = get_default($args, ['lambda', 0], 1.0);
                grokit_assert(is_numeric($lambda), 'ClusterGen: `lambda` parameter of exponential distribution must be a real number.');
                $lambda = floatval($lambda);
                grokit_assert($lambda > 0, 'ClusterGen: `lambda` parameter of exponential distribution must be in range (0, +inf).');
                $distArgs = [$lambda];
                break;
            case 'gamma':
            case 'Gamma':
                $distName = $distNS . '::' . 'gamma_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Gamma distribution takes at most 2 arguments.');
                $alpha = get_default($args, ['alpha', 0], 1.0);
                $beta = det_default($args, ['beta', 1], 1.0);
                grokit_assert(is_numeric($alpha), 'ClusterGen: `alpha` parameter of gamma distribution must be a real number.');
                grokit_assert(is_numeric($beta), 'ClusterGen: `beta` parameter of gamma distribution must be a real number.');
                $alpha = floatval($alpha);
                $beta = floatval($beta);
                $distArgs = [$alpha, $beta];
                break;
            default:
                grokit_error('ClusterGen: Unknown distribution ' . $name . ' given for center');
        }
        return [$distName, $distArgs];
    };
    $dists = [];
    $distArgs = [];
    $count = 0;
    $oType = '';
    $nCenters = 1;
    reset($outputs);
    foreach ($centers as $val) {
        $cluster = $val;
        if (is_functor($val)) {
            $cluster = [$val];
        } else {
            if (is_array($val)) {
                $nCenters = lcm($nCenters, \count($val));
            } else {
                grokit_error('ClusterGen: center descriptions must be functors or list of functors');
            }
        }
        $curDist = [];
        $curDistArgs = [];
        $curDistName = 'distribution' . $count++;
        $oType = strval(current($outputs));
        $iCount = 0;
        foreach ($cluster as $functor) {
            grokit_assert(is_functor($functor), 'ClusterGen: center description must be a functor');
            $vName = $curDistName . '_' . $iCount++;
            $ret = $handleDist($functor->name(), $functor->args(), $oType);
            $curDist[$vName] = $ret[0];
            $curDistArgs[$vName] = $ret[1];
        }
        next($outputs);
        $dists[$curDistName] = $curDist;
        $distArgs[$curDistName] = $curDistArgs;
    }
    // Determine the default number of sets to compute at a time.
    // We want to generate either $nTuples or 10,000 tuples, depending on which
    // is less.
    $defaultSetsTarget = min($nTuples, 10000);
    $setsToTarget = intval(ceil($defaultSetsTarget / $nCenters));
    $computeSets = get_default($t_args, 'compute.sets', $setsToTarget);
    grokit_assert(is_int($computeSets) && $computeSets > 0, 'ClusterGen: compute.sets must be a positive integer, ' . $computeSets . ' given');
    $className = generate_name('ClusterGen');
    // For some BIZZARE reason, the $outputs array was getting modified while
    // traversing over the $dists array. Making a deep copy of the outputs and
    // then reassigning it seems to fix the issue.
    $outputs = $myOutputs;
    ?>

class <?php 
    echo $className;
    ?>
 {

    // The number of tuples to produce per task
    static constexpr size_t N = <?php 
    echo $nTuples;
    ?>
;
    static constexpr size_t CacheSize = <?php 
    echo $computeSets * $nCenters;
    ?>
;

    // Typedefs
    typedef std::tuple<<?php 
    echo array_template('{val}', ', ', $outputs);
    ?>
> Tuple;
    typedef std::array<Tuple, CacheSize> TupleArray;
    typedef TupleArray::const_iterator TupleIterator;
    typedef <?php 
    echo $RNGtype;
    ?>
 RandGen;

    // Number of tuples produced.
    uintmax_t count;

    // Cache a number of outputs for efficiency
    TupleArray cache;
    TupleIterator cacheIt;

    // Random number generator
    RandGen rng;

    // Distributions
<?php 
    // This is the section causing issues.
    foreach ($dists as $name => $list) {
        foreach ($list as $vName => $type) {
            ?>
    <?php 
            echo $type;
            ?>
 <?php 
            echo $vName;
            ?>
;
<?php 
        }
        // foreach distribution
    }
    // foreach cluster set
    ?>

    // Helper function to generate tuples.
    void GenerateTuples(void) {
<?php 
    $tIndex = 0;
    foreach ($dists as $name => $list) {
        $lCenters = \count($list);
        // $nCenters has been defined to be the LCM of the number of centers in
        // any column, so $lCenter is guaranteed to divide evenly into
        // CacheSize
        ?>
        for( size_t index = 0; CacheSize > index; index += <?php 
        echo $lCenters;
        ?>
 ) {
<?php 
        $index = 0;
        foreach ($list as $vName => $type) {
            ?>
            std::get<<?php 
            echo $tIndex;
            ?>
>(cache[index + <?php 
            echo $index;
            ?>
]) = <?php 
            echo $vName;
            ?>
(rng);
<?php 
            $index++;
        }
        // foreach value in tuple
        ?>
        }
<?php 
        $tIndex++;
    }
    // foreach distribution
    ?>
        cacheIt = cache.cbegin();
    }

public:
    // Constructor
    <?php 
    echo $className;
    ?>
( GIStreamProxy & _stream ) :
        cache()
        , cacheIt()
        , count(0)
        , rng()
<?php 
    foreach ($dists as $name => $list) {
        foreach ($list as $vName => $type) {
            ?>
        , <?php 
            echo $vName;
            ?>
(<?php 
            echo implode(', ', $distArgs[$name][$vName]);
            ?>
)
<?php 
        }
        // foreach distribution
    }
    // foreach cluster set
    ?>

    {
<?php 
    if (is_null($seed)) {
        ?>
        <?php 
        echo $distNS;
        ?>
::random_device rd;
<?php 
    }
    // if seed is null
    ?>
        RandGen::result_type seed = <?php 
    echo is_null($seed) ? 'rd()' : "CongruentHash({$seed}, _stream.get_id() )";
    ?>
;
        rng.seed(seed);

        cacheIt = cache.cend();
    }

    // Destructor
    ~<?php 
    echo $className;
    ?>
(void) { }

    bool ProduceTuple(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
        if( N > count ) {
            if( cacheIt == cache.cend() ) {
                GenerateTuples();
            }
<?php 
    $tIndex = 0;
    foreach ($outputs as $name => $type) {
        ?>
            <?php 
        echo $name;
        ?>
 = std::get<<?php 
        echo $tIndex;
        ?>
>(*cacheIt);
<?php 
        $tIndex++;
    }
    // foreach output
    ?>

            ++cacheIt;
            ++count;

            return true;
        }
        else {
            return false;
        }
    }
};

<?php 
    return array('kind' => 'GI', 'name' => $className, 'output' => $outputs, 'system_headers' => $sys_headers, 'user_headers' => $user_headers, 'libraries' => $libraries);
}
Ejemplo n.º 9
0
 public function __construct($source)
 {
     $this->name = generate_name('json_val');
     $this->source = $source;
 }
Ejemplo n.º 10
0
function GroupBy(array $t_args, array $inputs, array $outputs, array $states)
{
    // Ensure we have valid inputs.
    if (\count($inputs) == 0) {
        // No inputs given, try to get them from template arguments.
        grokit_assert(array_key_exists('input', $t_args), 'No inputs given for GroupBy');
        $inputs = $t_args['input'];
        if (!is_array($inputs)) {
            $inputs = [$inputs];
        }
        foreach ($inputs as $name => &$type) {
            if (is_identifier($type)) {
                $type = lookupType(strval($type));
            }
            grokit_assert(is_datatype($type), 'Invalid type given for input ' . $name);
        }
    }
    grokit_assert(array_key_exists('group', $t_args), 'No groups specified for GroupBy');
    $gbyAttMap = $t_args['group'];
    grokit_assert(is_array($gbyAttMap), 'Invalid value given for groups, expected an expression name or list of expression names');
    $gbyAttMap = array_map('strval', $gbyAttMap);
    $gbyAttNames = array_keys($gbyAttMap);
    foreach ($gbyAttMap as $in => $out) {
        grokit_assert(array_key_exists($in, $inputs), 'Group ' . $in . ' not present in input');
        grokit_assert(array_key_exists($out, $outputs), 'Output Attribute ' . $out . ' for group ' . $in . ' not found in outputs');
    }
    $numGByAtts = \count($gbyAttNames);
    grokit_assert(array_key_exists('aggregate', $t_args), 'No aggregate specified for GroupBy');
    $innerGLA = $t_args['aggregate'];
    grokit_assert(is_gla($innerGLA), 'Non-GLA specified as aggregate for GroupBy');
    $debug = get_default($t_args, 'debug', 0);
    $init_size = get_default($t_args, 'init.size', 1024);
    $use_mct = get_default($t_args, 'use.mct', true);
    $keepHashes = get_default($t_args, 'mct.keep.hashes', false);
    grokit_assert(is_bool($keepHashes), 'GroupBy mct.keep.hashes argument must be boolean');
    // determine the result type
    $use_fragments = get_default($t_args, 'use.fragments', true);
    $resType = $use_fragments ? ['fragment', 'multi'] : ['multi'];
    $fragSize = get_default($t_args, 'fragment.size', 2000000);
    // Always support state
    $resType[] = 'state';
    // Class name randomly generated
    $className = generate_name("GroupBy");
    // instantiate the inner GLA. input/output is derived from the main input/output
    $gbyAtts = [];
    $gbyAttsOut = [];
    $glaInputAtts = [];
    $glaOutputAtts = [];
    foreach ($inputs as $name => $type) {
        if (in_array($name, $gbyAttNames)) {
            $gbyAtts[$name] = $type;
            $gbyAttsOut[$gbyAttMap[$name]] = $type;
            $outputs[$gbyAttMap[$name]] = $type;
        } else {
            $glaInputAtts[$name] = $type;
        }
    }
    foreach ($outputs as $name => $type) {
        if (!in_array($name, $gbyAttMap)) {
            $glaOutputAtts[$name] = $type;
        }
    }
    $innerGLA = $innerGLA->apply($glaInputAtts, $glaOutputAtts, $states);
    $libraries = $innerGLA->libraries();
    $innerRes = get_first_value($innerGLA->result_type(), ['multi', 'single', 'state']);
    if ($innerRes == 'state') {
        // If the result type is state, the only output is a state object
        // containing the GLA.
        $outputName = array_keys($glaOutputAtts)[0];
        $innerOutputs = [$outputName => lookupType('base::STATE', ['type' => $innerGLA])];
    } else {
        $innerOutputs = $innerGLA->output();
        grokit_assert(\count($innerOutputs) == \count($glaOutputAtts), 'Expected ' . \count($glaOutputAtts) . ' outputs fromm Inner GLA, got ' . \count($innerOutputs));
    }
    $constState = lookupResource('GroupByState', ['gla' => $innerGLA, 'groups' => $gbyAtts, 'debug' => $debug]);
    // constructor argumetns are inherited from inner GLA
    $configurable = $innerGLA->configurable();
    $reqStates = $innerGLA->req_states();
    // We need to specially create the constructor string because apparently
    // declaring Type Name(); is a function declaration instead of a variable
    // declaration for some reason.
    $constructorParts = [];
    if ($configurable) {
        $constructorParts[] = 'jsonInit';
    }
    if ($innerGLA->has_state()) {
        $constructorParts[] = 'innerState';
    }
    $constructorString = \count($constructorParts) > 0 ? '(' . implode(', ', $constructorParts) . ')' : '';
    // add the outputs we got from the gla
    foreach ($innerOutputs as $name => $type) {
        grokit_assert(array_key_exists($name, $outputs), 'Inner GLA\'s outputs refer to unknown attribute ' . $name);
        grokit_assert($type !== null, 'GroupBy Inner GLA left output ' . $name . ' with no type');
        $outputs[$name] = $type;
    }
    $iterable = $innerGLA->iterable();
    // need to keep track of system includes needed
    $extraHeaders = array();
    $allocatorText = "std::allocator<std::pair<const Key, {$innerGLA}> >";
    if ($use_mct) {
        $keepHashesText = $keepHashes ? 'true' : 'false';
        $extraHeaders[] = "mct/hash-map.hpp";
        $map = "mct::closed_hash_map<Key, {$innerGLA}, HashKey, std::equal_to<Key>, {$allocatorText}, {$keepHashesText}>";
        $mapType = 'mct::closed_hash_map';
    } else {
        $extraHeaders[] = "unordered_map";
        $map = "std::unordered_map<Key, {$innerGLA}, HashKey, std::equal_to<Key>, {$allocatorText}>";
        $mapType = 'std::unordered_map';
    }
    if ($debug > 0) {
        $extraHeaders[] = 'cstdio';
    }
    ?>


class <?php 
    echo $className;
    ?>
{
public:
    using ConstantState = <?php 
    echo $constState;
    ?>
;
<?php 
    if ($innerGLA->has_state()) {
        ?>
    using InnerState = ConstantState::InnerState;
<?php 
    }
    // if gla has state
    ?>
    using Key = ConstantState::Key;
    using HashKey = ConstantState::HashKey;
    using InnerGLA = <?php 
    echo $innerGLA;
    ?>
;

    typedef <?php 
    echo $map;
    ?>
 MapType;
    static const size_t INIT_SIZE = <?php 
    echo $init_size;
    ?>
;

public:
    class Iterator {
        MapType::iterator it; // current value
        MapType::iterator end; // last value in the fragment

    public:
        Iterator() { }

        Iterator(MapType::iterator _it, MapType::iterator _end):
            it(_it), end(_end)
        {
            if( it != end ) {

<?php 
    switch ($innerRes) {
        case 'multi':
            ?>
            it->second.Finalize();
<?php 
            break;
        case 'state':
            if ($innerGLA->finalize_as_state()) {
                ?>
            it->second.FinalizeState();
<?php 
            }
            // if we need to finalize as a state
            break;
    }
    // end switch inner restype
    ?>
            }
        }

        bool GetNextResult( <?php 
    echo typed_ref_args($outputs);
    ?>
 ) {
            bool gotResult = false;
            while( it != end && !gotResult ) {
                <?php 
    echo $innerGLA;
    ?>
 & gla = it->second;
<?php 
    foreach ($gbyAttMap as $in => $out) {
        ?>
                <?php 
        echo $out;
        ?>
 = it->first.<?php 
        echo $in;
        ?>
;
<?php 
    }
    // foreach grouping attribute
    ?>

<?php 
    switch ($innerRes) {
        case 'multi':
            ?>
                gotResult = gla.GetNextResult( <?php 
            echo args($innerOutputs);
            ?>
);
                if( !gotResult ) {
                    ++it;
                    if( it != end ) {
                        it->second.Finalize();
                    }
                }
<?php 
            break;
        case 'single':
            ?>
                gotResult = true;
                gla.GetResult(<?php 
            echo args($innerOutputs);
            ?>
);
                ++it;
<?php 
            break;
        case 'state':
            reset($innerOutputs);
            // Assuming that $innerOutputs contains a single value that is
            // the state type.
            $oName = key($innerOutputs);
            $oType = current($innerOutputs);
            ?>
                gotResult = true;
                <?php 
            echo $oName;
            ?>
 = <?php 
            echo $oType;
            ?>
( &gla );
                ++it;
<?php 
    }
    // switch inner result type
    ?>
            }

            return gotResult;
        }
    };

private:
    const ConstantState & constState;

<?php 
    if ($configurable) {
        ?>
    const Json::Value jsonInit;
<?php 
    }
    // if configurable
    ?>

    size_t count;

    MapType groupByMap;

    std::vector<MapType::iterator> theIterators;  // the iterators, only 2 elements if multi, many if fragment
    Iterator multiIterator;

public:

    <?php 
    echo $className;
    ?>
(<?php 
    if ($configurable) {
        ?>
const Json::Value & _jsonInit, <?php 
    }
    ?>
const ConstantState & _constState ) :
        constState(_constState)
<?php 
    if ($configurable) {
        ?>
        , jsonInit(_jsonInit)
<?php 
    }
    // if configurable
    ?>
        , count(0)
        , groupByMap( INIT_SIZE )
        , theIterators()
        , multiIterator()
    { }

    ~<?php 
    echo $className;
    ?>
() {}

    void Reset(void) {
        count = 0;
        groupByMap.clear();
        theIterators.clear();
    }

    void AddItem(<?php 
    echo array_template('const {val} & {key}', ', ', $inputs);
    ?>
) {
        count++;
        // check if _key is already in the map; if yes, add _value; else, add a new
        // entry (_key, _value)
        Key key(<?php 
    echo array_template('{key}', ', ', $gbyAtts);
    ?>
);

        MapType::iterator it = groupByMap.find(key);
        if (it == groupByMap.end()) { // group does not exist
            // create an empty GLA and insert
            // better to not add the item here so we do not have
            // to transport a large state

<?php 
    if ($innerGLA->has_state()) {
        ?>
            const InnerState & innerState = constState.getConstState(key);
<?php 
    }
    // if gla has state
    ?>
            InnerGLA gla<?php 
    echo $constructorString;
    ?>
;
            auto ret = groupByMap.insert(MapType::value_type(key, gla));
            it = ret.first; // reposition
        }
        it->second.AddItem(<?php 
    echo array_template('{key}', ', ', $glaInputAtts);
    ?>
);
    }

    void AddState(<?php 
    echo $className;
    ?>
& other) {
        count += other.count;
        // scan other hash and insert or update content in this one
        for (MapType::iterator it = other.groupByMap.begin(); it != other.groupByMap.end();
                ++it) {
            const Key& okey = it->first;
            <?php 
    echo $innerGLA;
    ?>
& ogla = it->second;

            MapType::iterator itt = groupByMap.find(okey);
            if (itt != groupByMap.end()) { // found the group
                <?php 
    echo $innerGLA;
    ?>
& gla = itt->second;
                gla.AddState(ogla);
            } else {
                // add the other group to this hash
                groupByMap.insert(MapType::value_type(okey, ogla));
            }
        }
    }

<?php 
    if ($iterable) {
        ?>
    bool ShouldIterate(ConstantState& modibleState) {
<?php 
        if ($debug > 0) {
            ?>
        fprintf(stderr, "<?php 
            echo $className;
            ?>
: ==== ShouldIterate ====\n");
<?php 
        }
        // if debugging enabled
        ?>
        bool shouldIterate = false;
        for( MapType::iterator it = groupByMap.begin(); it != groupByMap.end(); ++it ) {
            const Key & key = it->first;
            InnerGLA & gla = it->second;
<?php 
        if ($innerGLA->has_state()) {
            ?>
            InnerState & innerState = modibleState.getModibleState(key);
<?php 
        }
        // if gla has state
        ?>
            bool glaRet = gla.ShouldIterate(innerState);
            shouldIterate = shouldIterate || glaRet;
<?php 
        if ($debug > 0) {
            ?>
            fprintf(stderr, "<?php 
            echo $className;
            ?>
: Key(%s) shouldIterate(%s)\n",
                key.to_string().c_str(),
                glaRet ? "true" : "false");
<?php 
        }
        // if debugging enabled
        ?>
        }

        return shouldIterate;
    }
<?php 
    }
    // if iterable
    ?>

<?php 
    if (in_array('fragment', $resType)) {
        ?>

    int GetNumFragments(void){
        int size = groupByMap.size();
        int sizeFrag = <?php 
        echo $fragSize;
        ?>
;
        // setup the fragment boundaries
        // scan via iterator and count
        int frag=0;
        int pos=0;
        MapType::iterator it = groupByMap.begin();
        theIterators.clear();
        theIterators.push_back( it );
        // special case when size < num_fragments
        // >
        if (sizeFrag == 0){
            it = groupByMap.end();
            theIterators.push_back( it );
            return 1; // one fragment
        }

        while(it!=groupByMap.end()){
            while(it!=groupByMap.end() && pos<( frag + 1 )*sizeFrag){
//>
                ++it;
                pos++;
            }
            theIterators.push_back( it );
            frag++;
        }

<?php 
        if ($debug > 0) {
            ?>
        fprintf(stderr, "<?php 
            echo $className;
            ?>
: fragments(%d)\n", frag);
<?php 
        }
        ?>

        return frag;

    }

    Iterator* Finalize(int fragment){
        // Call finalize on all inner GLAs in this fragment.
        MapType::iterator iter = theIterators[fragment];
        MapType::iterator iterEnd = theIterators[fragment+1];

        Iterator* rez
            = new Iterator(theIterators[fragment], theIterators[fragment+1] );
        return rez;
    }

    bool GetNextResult(Iterator* it,  <?php 
        echo array_template('{val} & {key}', ', ', $outputs);
        ?>
) {
        return it->GetNextResult(<?php 
        echo args($outputs);
        ?>
);
    }
<?php 
    }
    // if using fragment interface
    ?>

    void Finalize() {
        multiIterator = Iterator( groupByMap.begin(), groupByMap.end() );

<?php 
    if ($debug >= 1) {
        ?>
        fprintf(stderr, "<?php 
        echo $className;
        ?>
: groups(%lu) tuples(%lu)\n", groupByMap.size(), count);
<?php 
    }
    ?>
    }

    bool GetNextResult(<?php 
    echo array_template('{val} & {key}', ', ', $outputs);
    ?>
) {
        return multiIterator.GetNextResult( <?php 
    echo args($outputs);
    ?>
 );
    }

    std::size_t size() const {
        return groupByMap.size();
    }

    const MapType& GetMap() const {
      return groupByMap;
    }

    bool Contains(<?php 
    echo const_typed_ref_args($gbyAtts);
    ?>
) const {
      Key key(<?php 
    echo args($gbyAtts);
    ?>
);
      return groupByMap.count(key) > 0;
    }

    const InnerGLA& Get(<?php 
    echo const_typed_ref_args($gbyAtts);
    ?>
) const {
      Key key(<?php 
    echo args($gbyAtts);
    ?>
);
      return groupByMap.at(key);
    }

    bool Contains(Key key) const {
      return groupByMap.count(key) > 0;
    }

    const InnerGLA& Get(Key key) const {
      return groupByMap.at(key);
    }
};

<?php 
    if (in_array('fragment', $resType)) {
        ?>
typedef <?php 
        echo $className;
        ?>
::Iterator <?php 
        echo $className;
        ?>
_Iterator;
<?php 
    }
    ?>

<?php 
    $sys_headers = array_merge(['iomanip', 'iostream', 'cstring'], $extraHeaders);
    return array('kind' => 'GLA', 'name' => $className, 'system_headers' => $sys_headers, 'user_headers' => array('HashFunctions.h'), 'input' => $inputs, 'output' => $outputs, 'result_type' => $resType, 'configurable' => $configurable, 'generated_state' => $constState, 'required_states' => $reqStates, 'iterable' => $iterable, 'properties' => ['resettable', 'finite container'], 'libraries' => $libraries, 'extra' => ['inner_gla' => $innerGLA]);
}
Ejemplo n.º 11
0
function parseCaseNoBase(&$source, &$cases, &$default)
{
    // The return type of the tests must be boolean
    $testRetType = lookupType('bool');
    // We don't know the return type yet, it will be defined by the cases.
    $retType = null;
    $retSource = null;
    // Generate a name for the return value of the case.
    $value_name = generate_name("case_value");
    $prep = [];
    $info = new ExpressionInfo($source, null, $value_name, true);
    grokit_logic_assert(count($cases) > 0, 'No cases found for case statement at ' . $source);
    // Handle cases
    foreach ($cases as $case) {
        $test = parseExpression(ast_get($case, NodeKey::TEST));
        $expr = parseExpression(ast_get($case, NodeKey::EXPR));
        $first = false;
        // Test if the return type of the test is compatible with boolean
        if (canConvert($test->type(), $testRetType)) {
            $test = convertExpression($test, $testRetType, $retSource);
        } else {
            // Incompatible types
            grokit_error('Case test expression has return type ' . $test->type() . ' which is incompatible with boolean ' . $test->source());
        }
        // If the return type is not set, set it and continue.
        // Otherwise, make sure the expression's return type is compatible with
        // the already set return type.
        if ($retType === null) {
            $retType = $expr->type();
            $retSource = $expr->source();
            $first = true;
            $info->setType($retType);
        } else {
            if (canConvert($expr->type(), $retType)) {
                // The types are compatible or the same, so make them the same.
                $expr = convertExpression($expr, $retType, $retSource);
            } else {
                // Incompatible types
                grokit_error('Case return type ' . $expr->type() . ' of expression at ' . $expr->source() . ' incompatible with previous return type ' . $retType . ' defined by expression at ' . $retSource);
            }
        }
        // Absorb the metadata from the test and expression into our info
        $info->absorbMeta($test);
        $info->absorbMeta($expr);
        $myPrep = '';
        if (!$first) {
            $myPrep .= 'else ';
        }
        $myPrep .= "if( {$test->value()} ) {$value_name} = {$expr->value()};";
        $prep[] = $myPrep;
    }
    // Handle default
    if ($default !== null) {
        if (canConvert($default->type(), $retType)) {
            $default = convertExpression($default, $retType, $retSource);
        } else {
            // Incompatible types.
            grokit_error('Case return type ' . $default->type() . ' of default at ' . $default->source() . ' incompatible with previous return type ' . $retType . ' defined by expression at ' . $retSource);
        }
        $info->absorbMeta($default);
        $prep[] = "else {$value_name} = {$default->value()};";
    }
    // Prepend the declaration of the return variable
    array_unshift($prep, "{$retType} {$value_name};");
    // Add all of our stuff as preprocesses
    $info->addPreprocesses($prep);
    if ($info->is_const()) {
        $info->makeConstant();
    }
    return $info;
}
Ejemplo n.º 12
0
function XMLReader(array $t_args, array $output)
{
    $my_output = [];
    foreach ($output as $key => $out) {
        $name = $key;
        $my_output[$name] = $out;
    }
    $xpath_row = $t_args['paths']['row'];
    $xpath_columns = $t_args['paths']['columns'];
    $className = generate_name('XMLReader');
    ?>

class <?php 
    echo $className;
    ?>
 {
    std::istream& my_stream;
    pugi::xml_document doc;
    const char* xpath_row;
    std::vector<const char*> xpath_columns;
    pugi::xpath_node_set rows;
    pugi::xpath_node_set::const_iterator start;
    pugi::xpath_node_set::const_iterator end;

    <?php 
    \grokit\declareDictionaries($my_output);
    ?>

public:
    <?php 
    echo $className;
    ?>
 ( GIStreamProxy& _stream ) :
        my_stream(_stream.get_stream( ))
    {
        doc.load( my_stream );

        xpath_row = "<?php 
    echo $xpath_row;
    ?>
";

        rows = doc.select_nodes(xpath_row);

        <?php 
    $push = 'xpath_columns.push_back("';
    $close_brace = '");';
    foreach ($xpath_columns as $col) {
        ?>
                <?php 
        echo $push;
        echo $col;
        echo $close_brace;
        ?>
        <?php 
    }
    ?>

        // Capture the first and last row
        start =  rows.begin();
        end = rows.end();
    }

    bool ProduceTuple( <?php 
    echo typed_ref_args($my_output);
    ?>
 ) 
    {

        if( start == end ) {
            return false;
        }
        else
        {   
            pugi::xml_node xmlnode = start->node();

            std::vector<const char*>::const_iterator it = xpath_columns.begin();

            <?php 
    $col_num = 0;
    $node_type = 'auto ';
    $select_single_node = ' = xmlnode.select_single_node(';
    $close = ');';
    $iterator_increment = '++it;';
    foreach ($my_output as $name => $type) {
        ?>
                    <?php 
        echo $node_type;
        echo ' col_';
        echo $col_num;
        echo $select_single_node;
        ?>
*it<?php 
        echo $close;
        ?>

                    <?php 
        echo \grokit\fromStringDict($name, $type, 'col_' . $col_num . '.node().child_value()');
        ?>
;

                    <?php 
        $col_num = $col_num + 1;
        ?>
                    <?php 
        echo $iterator_increment;
        ?>
            <?php 
    }
    ?>

            ++start;

            return true;
        }
    }
};

<?php 
    $sys_headers = ['vector', 'string', 'iostream', 'fstream'];
    return ['name' => $className, 'kind' => 'GI', 'output' => $my_output, 'system_headers' => $sys_headers, 'lib_headers' => ['pugixml.hpp']];
}
Ejemplo n.º 13
0
function Sum(array $t_args, array $inputs, array $outputs)
{
    $className = generate_name("Sum");
    $storage = [];
    $inits = [];
    if (\count($inputs) == 0) {
        $inputs = ["x" => lookupType("base::DOUBLE")];
        $storage = ["x" => 'long double'];
        $inits = ["x" => ''];
        $outputs = $inputs;
    } else {
        $oInputs = $inputs;
        reset($outputs);
        foreach ($oInputs as $name => $value) {
            if ($value->is('real')) {
                $storage[$name] = 'long double';
            } else {
                if ($value->is('integral')) {
                    $storage[$name] = 'long long int';
                } else {
                    if ($value == lookupType('base::BOOL')) {
                        $storage[$name] = 'long int';
                    } else {
                        $storage[$name] = $value->value();
                    }
                }
            }
            $oKey = key($outputs);
            if ($outputs[$oKey] === null) {
                if ($value->is('real')) {
                    $outputs[$oKey] = lookupType('base::DOUBLE');
                } else {
                    if ($value->is('integral') || $value == lookupType('base::BOOL')) {
                        $outputs[$oKey] = lookupType('base::BIGINT');
                    } else {
                        $outputs[$oKey] = $value;
                    }
                }
            }
            $inits[$name] = $value->has('init') ? $value->get('init') : '';
            next($outputs);
        }
    }
    ?>
class <?php 
    echo $className;
    ?>
 {
    <?php 
    echo array_template('{val} {key};' . PHP_EOL, '    ', $storage);
    ?>

public:
    <?php 
    echo $className;
    ?>
() : <?php 
    echo array_template('{key}({val})', ', ', $inits);
    ?>
    { }

    void AddItem(<?php 
    echo array_template('const {val}& _{key}', ', ', $inputs);
    ?>
) {
        <?php 
    echo array_template('{key} += _{key};' . PHP_EOL, '        ', $inputs);
    ?>
    }

    void AddState( <?php 
    echo $className;
    ?>
 & other ) {
        <?php 
    echo array_template('{key} += other.{key};' . PHP_EOL, '        ', $inputs);
    ?>
    }

    void GetResult( <?php 
    echo array_template('{val}& _{key}', ', ', $outputs);
    ?>
 ) const {
<?php 
    reset($outputs);
    reset($inputs);
    foreach ($outputs as $name => $type) {
        $inName = key($inputs);
        ?>
        _<?php 
        echo $name;
        ?>
 = <?php 
        echo $inName;
        ?>
;
<?php 
        next($inputs);
    }
    ?>
    }
};

<?php 
    return array('kind' => 'GLA', 'name' => $className, 'input' => $inputs, 'output' => $outputs, 'result_type' => 'single');
}
Ejemplo n.º 14
0
            $b = ($time - strtotime('Oct 17, 2014')) / 86400;
            // determine confirmed generated names
            $confirmed = $stats->api->confirmed / $a;
            // calculate avg generated names
            $stats->api->calculated = floor($confirmed * $b);
            // push new stats
            file_put_contents('stats.json', json_encode($stats));
        }
    }
    exit;
}
try {
    if ($amount < 1 || $amount > 500) {
        throw new Exception('Amount of requested names exceeds maximum allowed');
    }
    while ($count < $amount) {
        $name = generate_name($database, $region, $language, $gender);
        $name_length = iconv_strlen($name['name'] . ' ' . $name['surname']);
        if ($name_length >= $minlen && $name_length <= $maxlen) {
            $results[] = $name;
            $count++;
        }
    }
    if ($amount == 1) {
        send($results[0]);
    } else {
        send($results);
    }
} catch (Exception $e) {
    send(['error' => $e->getMessage()], 400);
}
Ejemplo n.º 15
0
function Average(array $t_args, array $input, array $output)
{
    $className = generate_name('Average');
    grokit_assert(\count($input) == \count($output), 'Average must have the same number of inputs and outputs');
    $outToIn = [];
    $internalTypes = [];
    $internalInit = [];
    reset($output);
    foreach ($input as $name => $type) {
        $outKey = key($output);
        $outToIn[$outKey] = $name;
        if ($type->is('numeric')) {
            $internalTypes[$name] = 'long double';
            $internalInit[$name] = '0.0';
        } else {
            $internalTypes[$name] = $type;
            $internalInit[$name] = '';
        }
        if (is_null(current($output))) {
            if ($type->is('numeric')) {
                $output[$outKey] = lookupType('base::DOUBLE');
            } else {
                $output[$outKey] = $type;
            }
        }
        next($output);
    }
    $countType = 'uint64_t';
    $debug = get_default($t_args, 'debug', 0);
    ?>
class <?php 
    echo $className;
    ?>
 {
private:

    <?php 
    echo $countType;
    ?>
 count; // keeps the number of tuples aggregated

<?php 
    foreach ($internalTypes as $name => $type) {
        ?>
    <?php 
        echo $type;
        ?>
 sum_<?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach internal value
    ?>

public:
    <?php 
    echo $className;
    ?>
() :
        count(0)
<?php 
    foreach ($internalInit as $name => $init) {
        ?>
        , sum_<?php 
        echo $name;
        ?>
(<?php 
        echo $init;
        ?>
)
<?php 
    }
    // foreach internal initializer
    ?>
    {}

    void AddItem(<?php 
    echo const_typed_ref_args($input);
    ?>
) {
        count++;

<?php 
    foreach ($input as $name => $type) {
        ?>
        sum_<?php 
        echo $name;
        ?>
 += <?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach input
    ?>
    }

    void AddState(<?php 
    echo $className;
    ?>
& o){
        count += o.count;
<?php 
    foreach ($input as $name => $type) {
        ?>
        sum_<?php 
        echo $name;
        ?>
 += o.sum_<?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach input
    ?>
    }

    // we only support one tuple as output
    void GetResult(<?php 
    echo typed_ref_args($output);
    ?>
) const {
        if( count > 0 ) {
<?php 
    foreach ($output as $name => $type) {
        $inName = $outToIn[$name];
        ?>
            <?php 
        echo $name;
        ?>
 = (sum_<?php 
        echo $inName;
        ?>
) / count;
<?php 
    }
    // foreach output
    ?>
        } else {
<?php 
    foreach ($output as $name => $type) {
        ?>
            <?php 
        echo $name;
        ?>
 = sum_<?php 
        echo $inName;
        ?>
;
<?php 
    }
    // foreach output
    ?>
        }
    }

};

<?php 
    $sys_headers = ['cinttypes'];
    if ($debug > 0) {
        $sys_headers[] = 'iostream';
        $sys_headers[] = 'sstream';
    }
    return array('kind' => 'GLA', 'name' => $className, 'system_headers' => $sys_headers, 'input' => $input, 'output' => $output, 'result_type' => 'single');
}
Ejemplo n.º 16
0
function Max(array $t_args, array $input, array $output)
{
    grokit_assert(\count($output) >= 1, 'Max GLA  produces at least one output!');
    grokit_assert(\count($output) == \count($input), 'Max GLA should have the same number of inputs and outputs');
    $nValues = \count($output);
    $inputNames = array_keys($input);
    $outputNames = array_keys($output);
    // Outputs should be the same type as the inputs
    for ($index = 0; $index < $nValues; $index++) {
        array_set_index($output, $index, array_get_index($input, $index));
    }
    $name = generate_name('Max_');
    ?>
class <?php 
    echo $name;
    ?>
 {
    uintmax_t count;

<?php 
    foreach ($output as $k => $v) {
        ?>
    <?php 
        echo $v;
        ?>
 _<?php 
        echo $k;
        ?>
;
<?php 
    }
    // foreach output
    ?>

public:
    <?php 
    echo $name;
    ?>
() :
<?php 
    foreach ($output as $k => $v) {
        ?>
        _<?php 
        echo $k;
        ?>
(),
<?php 
    }
    // foreach output
    ?>
        count(0)
    { }

    void AddItem( <?php 
    echo const_typed_ref_args($input);
    ?>
 ) {
        if( count > 0 ) {
<?php 
    for ($index = 0; $index < $nValues; $index++) {
        ?>
            _<?php 
        echo $outputNames[$index];
        ?>
 = std::max(_<?php 
        echo $outputNames[$index];
        ?>
, <?php 
        echo $inputNames[$index];
        ?>
);
<?php 
    }
    // foreach value
    ?>
        } else {
<?php 
    for ($index = 0; $index < $nValues; $index++) {
        ?>
            _<?php 
        echo $outputNames[$index];
        ?>
 = <?php 
        echo $inputNames[$index];
        ?>
;            
<?php 
    }
    // foreach value
    ?>
        }

        count++;
    }
    void AddState( <?php 
    echo $name;
    ?>
 & o ) {
        if (count > 0 && o.count > 0) {
<?php 
    for ($index = 0; $index < $nValues; $index++) {
        ?>
            _<?php 
        echo $outputNames[$index];
        ?>
 = std::max(_<?php 
        echo $outputNames[$index];
        ?>
, o._<?php 
        echo $outputNames[$index];
        ?>
);
<?php 
    }
    // foreach value
    ?>
        } else if(o.count > 0) { // count == 0
<?php 
    for ($index = 0; $index < $nValues; $index++) {
        ?>
            _<?php 
        echo $outputNames[$index];
        ?>
 = o._<?php 
        echo $outputNames[$index];
        ?>
;            
<?php 
    }
    // foreach value
    ?>
        }
        // Otherwise, count > 0 && o.count == 0, so just keep our values

        count += o.count;
    }

    void GetResult(<?php 
    echo typed_ref_args($output);
    ?>
) {
<?php 
    foreach ($output as $k => $v) {
        ?>
        <?php 
        echo $k;
        ?>
 = _<?php 
        echo $k;
        ?>
;
<?php 
    }
    // foreach output
    ?>
    }
};
<?php 
    return ['kind' => 'GLA', 'name' => $name, 'input' => $input, 'output' => $output, 'result_type' => 'single', 'system_headers' => ['algorithm', 'cstdint']];
}
Ejemplo n.º 17
0
function ExtremeTuples(array $t_args, array $inputs, array $outputs)
{
    $extremes = get_first_key($t_args, ['extremes']);
    $nExt = \count($extremes);
    grokit_assert($nExt > 0, 'No extremes specified for ExtremeTuples GLA.');
    if (\count($inputs) == 0) {
        grokit_assert(array_key_exists('inputs', $t_args), 'No arguments specified for ExtremeTuples GLA.');
        $count = 0;
        foreach ($t_args['inputs'] as $type) {
            if (is_identifier($type)) {
                $type = lookupType(strval($type));
            }
            grokit_assert(is_datatype($type), 'Only datatypes can be specified as inputs to ' . 'the ExtremeTuples GLA');
            $name = 'et_val' . $count;
            $inputs[$name] = $type;
        }
    }
    $outputMap = [];
    reset($outputs);
    foreach ($inputs as $name => $type) {
        $oKey = key($outputs);
        $outputs[$oKey] = $type;
        $outputMap[$oKey] = $name;
        next($outputs);
    }
    grokit_assert($nExt <= \count($inputs), 'There can not be more extreme values than there are inputs!');
    $mainAtts = [];
    $extraAtts = [];
    $minOpts = ['MIN', 'MINIMUM', '-', '<'];
    $maxOpts = ['MAX', 'MAXIMUM', '+', '>'];
    $inArrayCase = function ($needle, $haystack) {
        foreach ($haystack as $item) {
            if (strcasecmp($needle, $item) == 0) {
                return true;
            }
        }
        return false;
    };
    $minimum = [];
    foreach ($extremes as $name => $val) {
        grokit_assert(array_key_exists($name, $inputs), "ExtremeTuples: Expression with name " . $name . " specified as extreme not found in inputs");
    }
    foreach ($inputs as $name => $type) {
        if (array_key_exists($name, $extremes)) {
            $mainAtts[$name] = $type;
            if ($inArrayCase($extremes[$name], $minOpts)) {
                $minimum[$name] = true;
            } else {
                if ($inArrayCase($extremes[$name], $maxOpts)) {
                    $minimum[$name] = false;
                } else {
                    grokit_error('Unknown extreme type ' . $extremes[$name] . ' specified for ' . $name);
                }
            }
        } else {
            $extraAtts[$name] = $type;
        }
    }
    $debug = get_default($t_args, 'debug', 0);
    $className = generate_name('ExtremeTuples');
    ?>

class <?php 
    echo $className;
    ?>
 {

    struct Tuple {
<?php 
    foreach ($inputs as $name => $type) {
        ?>
        <?php 
        echo $type;
        ?>
 <?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach input
    ?>

        // Default Constructor, Copy Constructor, and Copy Assignment are all
        // default
        Tuple(void) = default;
        Tuple(const Tuple &) = default;
        Tuple & operator = (const Tuple &) = default;

        Tuple(<?php 
    echo array_template('const {val} & _{key}', ', ', $inputs);
    ?>
) :
            <?php 
    echo array_template('{key}(_{key})', ', ', $inputs);
    ?>

        { }

        // operator > means that this tuple is "better" than the other tuple.
        bool operator > ( const Tuple & other ) const {
<?php 
    foreach ($mainAtts as $name => $type) {
        $op1 = $minimum[$name] ? '<' : '>';
        $op2 = !$minimum[$name] ? '<' : '>';
        ?>
            if( <?php 
        echo $name;
        ?>
 <?php 
        echo $op1;
        ?>
 other.<?php 
        echo $name;
        ?>
 )
                return true;
            else if( <?php 
        echo $name;
        ?>
 <?php 
        echo $op2;
        ?>
 other.<?php 
        echo $name;
        ?>
 )
                return false;
<?php 
    }
    // foreach main attribute
    ?>

            return false;
        }

        bool operator < ( const Tuple& other ) const {
            return other > *this;
        }

        bool operator <= (const Tuple & other ) const {
            return ! (*this > other );
        }

        bool operator >= (const Tuple & other ) const {
            return !( other > *this );
        }

        bool operator == (const Tuple & other ) const {
            bool ret = true;
<?php 
    foreach ($mainAtts as $name => $type) {
        ?>
            ret &= <?php 
        echo $name;
        ?>
 == other.<?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach main attribute
    ?>
            return ret;
        }
    }; // struct Tuple

    typedef std::vector<Tuple> TupleVector;
public:
    class Iterator {
    public:
        typedef TupleVector::const_iterator iter_type;

    private:
        iter_type begin;
        iter_type end;

    public:
        Iterator(void) = default;
        Iterator(const Iterator &) = default;
        Iterator( const iter_type & _begin, const iter_type & _end ) : begin(_begin), end(_end)
        { }
        Iterator( const iter_type && _begin, const iter_type && _end ) : begin(_begin), end(_end)
        { }

        bool GetNextResult(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
            if( begin != end ) {
<?php 
    foreach ($outputs as $name => $type) {
        ?>
                <?php 
        echo $name;
        ?>
 = begin-><?php 
        echo $outputMap[$name];
        ?>
;
<?php 
    }
    ?>
                begin++;
                return true;
            }
            else {
                return false;
            }
        }

    };

private:

    uintmax_t __count;  // number of tuples covered

    TupleVector tuples;

    // Iterator for multi output type
    Iterator multiIterator;

public:
    // Constructor and destructor
    <?php 
    echo $className;
    ?>
(void) : __count(0), tuples(), multiIterator()
    { }

    ~<?php 
    echo $className;
    ?>
() { }

    void AddItem( <?php 
    echo const_typed_ref_args($inputs);
    ?>
 ) {
        ++__count;
        Tuple t(<?php 
    echo args($inputs);
    ?>
);

        if( tuples.empty() ) {
            tuples.push_back(t);
        }
        else if( t > tuples.front() ) {
            tuples.clear();
            tuples.push_back(t);
        }
        else if( t == tuples.front() ) {
            tuples.push_back(t);
        }
    }

    void AddState( <?php 
    echo $className;
    ?>
 & other ) {
        if( tuples.size() == 0 ) {
            tuples.swap(other.tuples);
        }
        else if( other.tuples.size() == 0 ) {
            // Do nothing
        }
        else if( tuples.front() > other.tuples.front() ) {
            // fast path
        }
        else if( other.tuples.front() > tuples.front() ) {
            tuples.swap(other.tuples);
        }
        else {
            for( Tuple & t : other.tuples ) {
                tuples.push_back(t);
            }
        }
    }

    void Finalize( void ) {
        multiIterator = Iterator(tuples.cbegin(), tuples.cend());
    }

    bool GetNextResult(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
        return multiIterator.GetNextResult(<?php 
    echo args($outputs);
    ?>
);
    }
}; // class <?php 
    echo $className;
    ?>

<?php 
    $system_headers = ['vector', 'algorithm', 'cinttypes'];
    if ($debug > 0) {
        $system_headers = array_merge($system_headers, ['iostream', 'sstream', 'string']);
    }
    return array('kind' => 'GLA', 'name' => $className, 'input' => $inputs, 'output' => $outputs, 'result_type' => 'multi', 'system_headers' => $system_headers);
}
Ejemplo n.º 18
0
/**
 *  A GLA that determines the distinct values of a dataset.
 */
function Distinct(array $t_args, array $input, array $output)
{
    grokit_assert(\count($input) == \count($output), 'Distinct must have the same outputs as inputs.');
    $outputsToInputs = [];
    $i = 0;
    foreach ($input as $name => $type) {
        $outputsToInputs[array_keys($output)[$i]] = $name;
        array_set_index($output, $i++, $type);
    }
    $useMCT = get_default($t_args, 'use.mct', true);
    $initSize = get_default($t_args, 'init.size', 65536);
    $keepHashes = get_default($t_args, 'mct.keep.hashes', false);
    $fragmentSize = get_default($t_args, 'fragment.size', 100000);
    $nullCheck = get_default($t_args, 'null.check', false);
    grokit_assert(is_bool($useMCT), 'Distinct use.mct argument must be boolean');
    grokit_assert(is_integer($initSize), 'Distinct init.size argument must be an integer');
    grokit_assert($initSize > 0, 'Distinct init.size argument must be positive');
    grokit_assert(is_bool($keepHashes), 'Distinct mct.keep.hashes argument must be boolean');
    grokit_assert(is_integer($fragmentSize), 'Distinct fragment.size argument must be integral');
    grokit_assert($fragmentSize > 0, 'Distinct fragment.size argumenst must be positive');
    $nullable = [];
    if (is_bool($nullCheck)) {
        foreach ($input as $name => $type) {
            $nullable[$name] = $nullCheck;
        }
    } else {
        if (is_array($nullCheck)) {
            foreach ($input as $name => $type) {
                $nullable[$name] = false;
            }
            foreach ($nullCheck as $index => $n) {
                grokit_assert(is_string($n), 'Distinct null.check has invalid value at position ' . $index);
                grokit_assert(array_key_exists($n, $nullable), 'Distinct null.check has unknown input ' . $n . ' at position ' . $index);
                $nullable[$n] = true;
            }
        } else {
            grokit_error('Distinct null.check must be boolean or list of inputs to check for nulls');
        }
    }
    $keepHashesText = $keepHashes ? 'true' : 'false';
    $system_headers = ['cinttypes', 'functional', 'vector'];
    if ($useMCT) {
        $system_headers[] = 'mct/hash-set.hpp';
        $definedSet = "mct::closed_hash_set<Key, HashKey, std::equal_to<Key>, std::allocator<Key>, {$keepHashesText}>";
    } else {
        $system_headers[] = 'unordered_map';
        $definedSet = "std::unordered_set<Key, HashKey, std::equal_to<Key>, std::allocator<Key>>";
    }
    $className = generate_name('Distinct');
    ?>
class <?php 
    echo $className;
    ?>
 {

    public:
    // Value being placed into the set.
    struct Key {
<?php 
    foreach ($input as $name => $type) {
        ?>
        <?php 
        echo $type;
        ?>
 <?php 
        echo $name;
        ?>
;
<?php 
    }
    // for each input
    ?>

        // Construct the value by copying all of the attributes.
        Key(<?php 
    echo const_typed_ref_args($input);
    ?>
) :
<?php 
    $first = true;
    foreach ($input as $name => $type) {
        ?>
            <?php 
        echo $first ? ' ' : ',';
        ?>
 <?php 
        echo $name;
        ?>
(<?php 
        echo $name;
        ?>
)
<?php 
        $first = false;
    }
    // for each input
    ?>
        { }

        bool operator==(const Key & o ) const {
            return true <?php 
    echo array_template("&& ({key} == o.{key})", ' ', $input);
    ?>
;
        }

        size_t hash_value() const {
            uint64_t hash = H_b;
<?php 
    foreach ($input as $name => $type) {
        ?>
            hash = CongruentHash(Hash(<?php 
        echo $name;
        ?>
), hash);
<?php 
    }
    // for each input
    ?>
            return size_t(hash);
        }
    };

    // Hashing functor for our value
    struct HashKey {
        size_t operator()(const Key& o) const {
            return o.hash_value();
        }
    };

    using Set = <?php 
    echo $definedSet;
    ?>
;

    // Iterator object used in multi and fragment result types
    class Iterator {
        public:
        using iterator_t = Set::const_iterator;

        private:

        iterator_t start;
        iterator_t end;

        public:

        Iterator() : start(), end() { }

        Iterator( const iterator_t & _start, const iterator_t & _end ) :
            start(_start), end(_end)
        { }

        Iterator( const Iterator & o ) : start(o.start), end(o.end)
        { }

        bool GetNextResult(<?php 
    echo typed_ref_args($output);
    ?>
) {
            if( start != end ) {
<?php 
    foreach ($output as $name => $type) {
        ?>
                <?php 
        echo $name;
        ?>
 = start-><?php 
        echo $outputsToInputs[$name];
        ?>
;
<?php 
    }
    // for each output
    ?>
                start++;
                return true;
            } else {
                return false;
            }
        }
    };

    private:

    // Constants
    static constexpr size_t INIT_SIZE = <?php 
    echo $initSize;
    ?>
;
    static constexpr size_t FRAG_SIZE = <?php 
    echo $fragmentSize;
    ?>
;

    // Member variables

    uint64_t count;         // Total # tuples seen

    Set distinct;           // Set of distinct values

    using IteratorList = std::vector<Iterator>;

    Iterator multiIterator;     // Internal iterator for multi result type
    IteratorList fragments;     // Iterator for fragments

    public:

    <?php 
    echo $className;
    ?>
() :
        count(0),
        distinct(INIT_SIZE),
        multiIterator(),
        fragments()
    { }

    ~<?php 
    echo $className;
    ?>
() { }

    void Reset(void) {
        count = 0;
        distinct.clear();
    }

    void AddItem(<?php 
    echo const_typed_ref_args($input);
    ?>
) {
        count++;
<?php 
    foreach ($nullable as $name => $check) {
        if ($check) {
            ?>
        if( IsNull( <?php 
            echo $name;
            ?>
 ) ) return;
<?php 
        }
        // if checking for nulls
    }
    // foreach input
    ?>

        Key key(<?php 
    echo args($input);
    ?>
);

        distinct.insert(key);
/*
        auto it = distinct.find(key);
        if( it == distinct.end() ) {
            distinct.insert(key);
        }
*/
    }

    void AddState( <?php 
    echo $className;
    ?>
 & other ) {
        for( auto & elem : other.distinct ) {
            distinct.insert(elem);
            /*
            auto it = distinct.find(elem);
            if( it == distinct.end() ) {
                distinct.insert(elem);
            }
            */
        }
        count += other.count;
    }

    // Multi interface
    void Finalize(void) {
        multiIterator = Iterator(distinct.cbegin(), distinct.cend());
    }

    bool GetNextResult(<?php 
    echo typed_ref_args($output);
    ?>
) {
        return multiIterator.GetNextResult(<?php 
    echo args($output);
    ?>
);
    }

    // Fragment interface
    int GetNumFragments(void) {
        fragments.clear();
        int nFrag = 0;

        Iterator::iterator_t prev = distinct.cbegin();
        Iterator::iterator_t end = distinct.cend();
        Iterator::iterator_t next = prev;

        while( next != end ) {
            for( size_t i = 0; next != end && FRAG_SIZE > i; i++ ) {
                next++;
            }
            Iterator nIter(prev, next);
            fragments.push_back(nIter);

            prev = next;
            nFrag++;
        }

        return nFrag;
    }

    Iterator * Finalize(int fragment) {
        return new Iterator(fragments[fragment]);
    }

    bool GetNextResult(Iterator * it, <?php 
    echo typed_ref_args($output);
    ?>
) {
        return it->GetNextResult(<?php 
    echo args($output);
    ?>
);
    }

    // General methods
    uint64_t get_count() const {
        return count;
    }

    uint64_t get_countDistinct() const {
        return distinct.size();
    }

    const Set & get_distinct() const {
        return distinct;
    }
};

typedef <?php 
    echo $className;
    ?>
::Iterator <?php 
    echo $className;
    ?>
_Iterator;
<?php 
    return ['kind' => 'GLA', 'name' => $className, 'input' => $input, 'output' => $output, 'result_type' => ['multi', 'fragment'], 'user_headers' => ['HashFunctions.h'], 'system_headers' => $system_headers, 'properties' => ['resettable']];
}
Ejemplo n.º 19
0
$csv_delimiter = $csv_delimiter == '\\t' ? "\t" : $csv_delimiter;
$newline = "\n";
// need this be system dependent?
// output the column headers
$columns = array();
foreach ($template as $col) {
    $columns[] = $col[0];
}
echo join("{$csv_delimiter}", $columns) . $newline;
for ($row = 1; $row <= $g_numResults; $row++) {
    $row_vals = array();
    foreach ($template as $col) {
        // display the appropriate thing, based on the data type
        switch ($col[1]) {
            case "Name":
                $row_vals[] = generate_name($col[2][0], $g_male_names, $g_female_names, $g_names, $g_surnames);
                break;
            case "Phone":
                $row_vals[] = generate_random_num_str($col[2][0]);
                break;
            case "Email":
                $row_vals[] = generate_email_address($g_words);
                break;
            case "Street-Address":
                $row_vals[] = generate_street_address($g_words);
                break;
            case "City":
                $row_vals[] = $g_cities[rand(0, count($g_cities) - 1)];
                break;
            case "Postal-Zip":
                $wants_canada_postal = $col[2][0];
Ejemplo n.º 20
0
function STATE(array $t_args)
{
    $type = get_first_key($t_args, ['type', '0']);
    grokit_assert(is_gla($type), 'Template argument to STATE must be a valid GLA.');
    $type = $type->lookup();
    $gContent = '';
    $functions = [];
    $methods = [];
    $className = generate_name('STATE_');
    ?>

/** Type definition for generic GLA states. This type is only used to
    trannsport states withing the same memory space between
    operators. The object the state points to MUST be treated like a
    const.

    Note: this type cannot be read from the disk or written to the
    output. A different mechanism will be used for that.

    The type in the object must be a hash of the name of the class
    used to encode the object. Any function that assumes a certain
    type must explicitly verify the correctness of the type.

    The object can be manipulated like a basic datatype. STATE objects
    do not know how to deallocate the memory they use. Other
    mechanisms have to be used to ensure correct deallocation
    (acknowledgements of data packets that contain this as members).

**/

class <?php 
    echo $className;
    ?>
 {
public:
    typedef <?php 
    echo $type;
    ?>
* pointer_type;
    typedef uint64_t hash_type;

private:
    pointer_type object;
    hash_type type;

public:

    <?php 
    echo $className;
    ?>
():
        object(nullptr),
        type(0)
    {}
    <?php 
    echo $className;
    ?>
(pointer_type _object):
        object(_object),
        type(<?php 
    echo $type->cHash();
    ?>
)
    {}

    pointer_type GetObject() const {
        FATALIF(type != <?php 
    echo $type->cHash();
    ?>
, "STATE contains incorrect type!");
        return object;
    }

<?php 
    $methods[] = ['IsNull', [], 'BASE::BOOL', true];
    ?>
    bool IsNull() const {
        return object == nullptr;
    }

    /** no destructor. object should not be deallocated here */
};

<?php 
    ob_start();
    ?>

<?php 
    $functions[] = ['IsNull', ['@type'], 'BASE::BOOL', true, true];
    ?>
inline
bool IsNull( const @type & d ) {
    return d.IsNull();
}

<?php 
    $gContent .= ob_get_clean();
    ?>

<?php 
    return array('kind' => 'TYPE', 'name' => $className, "complex" => false, 'extras' => ['type' => $type], 'properties' => ['__state__'], 'global_content' => $gContent, 'methods' => $methods, 'functions' => $functions);
}
Ejemplo n.º 21
0
/**
 *  A GLA that estimates the cardinality of a dataset using a bloom filter of
 *  a configurable size.
 *
 *  Note: This filter has very high performance, so long as all of the states
 *  fit into cache, preferably L1 or L2, but L3 is also fine. Once the states
 *  are large enough that all of them cannot fit inside L3 cache at the same
 *  time, performance takes a nose dive (4x loss minimum).
 */
function BloomFilter(array $t_args, array $input, array $output)
{
    grokit_assert(\count($output) == 1, 'BloomFilter produces only 1 value, ' . \count($output) . ' outputs given.');
    $outputName = array_keys($output)[0];
    $outputType = array_get_index($output, 0);
    if (is_null($outputType)) {
        $outputType = lookupType('BASE::BIGINT');
    }
    $output[$outputName] = $outputType;
    grokit_assert($outputType->is('numeric'), 'BloomFilter output must be numeric!');
    $exp = get_first_key_default($t_args, ['exponent'], 16);
    grokit_assert(is_integer($exp), 'BloomFilter exponent must be an integer.');
    grokit_assert($exp > 0 && $exp < 64, 'BloomFilter exponent must be in range (0,64), ' . $exp . ' given.');
    $nullCheck = get_default($t_args, 'null.check', false);
    $nullable = [];
    if (is_bool($nullCheck)) {
        foreach ($input as $name => $type) {
            $nullable[$name] = $nullCheck;
        }
    } else {
        if (is_array($nullCheck)) {
            foreach ($input as $name => $type) {
                $nullable[$name] = false;
            }
            foreach ($nullCheck as $index => $n) {
                grokit_assert(is_string($n), 'BloomFilster null.check has invalid value at position ' . $index);
                grokit_assert(array_key_exists($n, $nullable), 'BloomFilster null.check has unknown input ' . $n . ' at position ' . $index);
                $nullable[$n] = true;
            }
        } else {
            grokit_error('BloomFilster null.check must be boolean or list of inputs to check for nulls');
        }
    }
    $debug = get_default($t_args, 'debug', 0);
    $bits = pow(2, $exp);
    $bytes = ceil($bits / 8.0);
    // Calculate the number of bits set for every possible value of a byte
    $nBits = [];
    for ($i = 0; $i < 256; $i++) {
        $n = $i;
        $b = 0;
        while ($n > 0) {
            $n &= $n - 1;
            $b++;
        }
        $nBits[$i] = $b;
    }
    $className = generate_name('BloomFilter');
    ?>
class <?php 
    echo $className;
    ?>
 {
    static constexpr size_t BITS = <?php 
    echo $bits;
    ?>
;
    static constexpr size_t BYTES = <?php 
    echo $bytes;
    ?>
;
    static constexpr size_t MASK = BITS - 1;
    static constexpr std::array<unsigned char, 256> BITS_SET = { <?php 
    echo implode(', ', $nBits);
    ?>
 };
    static constexpr std::array<unsigned char, 8> BIT_MASKS = {
        0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
    };

    size_t count;

    std::array<unsigned char, BYTES> set;
    //unsigned char set[BYTES];
    //std::bitset<BITS> set;

public:
    <?php 
    echo $className;
    ?>
() : count(0), set() {
        for( size_t i = 0; i < BYTES; i++ ) { //>
            set[i] = 0;
        }
    }

    ~<?php 
    echo $className;
    ?>
() { }

    void AddItem( <?php 
    echo const_typed_ref_args($input);
    ?>
 ) {
        count++;
<?php 
    foreach ($nullable as $name => $check) {
        if ($check) {
            ?>
        if( IsNull( <?php 
            echo $name;
            ?>
 ) ) return;
<?php 
        }
        // if checking for nulls
    }
    // foreach input
    ?>
        size_t hashVal = H_b;
<?php 
    foreach ($input as $name => $type) {
        ?>
        hashVal = CongruentHash(Hash(<?php 
        echo $name;
        ?>
), hashVal);
<?php 
    }
    // foreach input
    ?>
        hashVal = hashVal & MASK;
        const size_t bucket = hashVal >> 3;
        const size_t bucket_index = hashVal & 0x07;
        const unsigned char mask = BIT_MASKS[bucket_index];
        set[bucket] |= mask;
    }

    void AddState( <?php 
    echo $className;
    ?>
 & o ) {
        count += o.count;
        for( size_t i = 0; i < BYTES; i++ ) { //>
            set[i] |= o.set[i];
        }
    }

    void GetResult( <?php 
    echo $outputType;
    ?>
 & <?php 
    echo $outputName;
    ?>
 ) {
        size_t nBitsSet = 0;
        constexpr long double bits = static_cast<long double>(BITS);
        for( size_t i = 0; i < BYTES; i++ ) { //>
            nBitsSet += BITS_SET[set[i]];
        }
        long double bitsSet = static_cast<long double>(nBitsSet);

        if( nBitsSet == BITS ) {
            // All Bits set, just give the cardinality as an estimate.
            <?php 
    echo $outputName;
    ?>
 = count;
        } else {
            long double cardinality = - bits * std::log(1 - (bitsSet / bits));
            <?php 
    echo $outputName;
    ?>
 = cardinality;
        }

<?php 
    if ($debug > 0) {
        ?>
        std::cout << "BloomFilter:"
            << " bitsSet(" << bitsSet << ")"
            << " bits(" << bits << ")"
            << " cardinality(" << cardinality << ")"
            << " output(" << <?php 
        echo $outputName;
        ?>
 << ")"
            << std::endl;; //>
<?php 
    }
    // if debugging enabled
    ?>
    }
};

// Storage for static members
constexpr std::array<unsigned char, 256> <?php 
    echo $className;
    ?>
::BITS_SET;
constexpr std::array<unsigned char, 8> <?php 
    echo $className;
    ?>
::BIT_MASKS;
<?php 
    $system_headers = ['cmath', 'array'];
    if ($debug > 0) {
        $system_headers[] = 'iostream';
    }
    return ['kind' => 'GLA', 'name' => $className, 'input' => $input, 'output' => $output, 'result_type' => 'single', 'user_headers' => ['HashFunctions.h'], 'system_headers' => $system_headers];
}
Ejemplo n.º 22
0
function CCompLP($t_args, $inputs, $outputs)
{
    // Class name is randomly generated.
    $className = generate_name('CComp');
    // Initializiation of argument names.
    $inputs_ = array_combine(['s', 't'], $inputs);
    $vertex = $inputs_['s'];
    // Construction of outputs.
    $outputs_ = ['node' => $vertex, 'component' => lookupType('int')];
    $outputs = array_combine(array_keys($outputs), $outputs_);
    $sys_headers = ['armadillo', 'algorithm'];
    $user_headers = [];
    $lib_headers = [];
    $libraries = ['armadillo'];
    $properties = [];
    $extra = [];
    $result_type = ['multi'];
    ?>

using namespace arma;
using namespace std;

class <?php 
    echo $className;
    ?>
;

<?php 
    $constantState = lookupResource('graph::CCompLP_Constant_State', ['className' => $className]);
    ?>

class <?php 
    echo $className;
    ?>
 {
 public:
  // The constant state for this GLA.
  using ConstantState = <?php 
    echo $constantState;
    ?>
;

  // The number of iterations to perform, not counting the initial set-up.
  static const constexpr int kIterations = 30;

  // The work is split into chunks of this size before being partitioned.
  static const constexpr int kBlock = 32;

  // The maximum number of fragments to use.
  static const constexpr int kMaxFragments = 64;

 private:
  
  // Node Component
  static arma::rowvec node_component;

  // The typical constant state for an iterable GLA.
  const ConstantState& constant_state;

  // The number of unique nodes seen.
  long num_nodes;

  // 
  long output_iterator;

  // The current iteration.
  int iteration;
  
  // check if need more iterations
  long connections;

 public:
  <?php 
    echo $className;
    ?>
(const <?php 
    echo $constantState;
    ?>
& state)
      : constant_state(state),
        num_nodes(state.num_nodes),
        iteration(state.iteration),output_iterator(0),connections(0) {
  }

  // Basic dynamic array allocation.
  void AddItem(<?php 
    echo const_typed_ref_args($inputs_);
    ?>
) {
    if (iteration == 0) {
      num_nodes = max((long) max(s, t), num_nodes);
      return;
    } /*else if (iteration == 1){
      long max_known = (long) max(s, t);
      node_component(s) = max_known;
      node_component(t) = max_known;
      ++ connections;
    }*/else{
      long s_id = node_component(s), t_id = node_component(t);
      if (s_id != t_id){
        ++ connections;
        if (s_id > t_id)
          node_component(t) = s_id;
        else
          node_component(s) = t_id;
      }
    }
  }

  // Hashes are merged.
  void AddState(<?php 
    echo $className;
    ?>
 &other) {
    if (iteration == 0)
      num_nodes = max(num_nodes, other.num_nodes);
    else
      connections += other.connections;
  }

  // Most computation that happens at the end of each iteration is parallelized
  // by performed it inside Finalize.
  bool ShouldIterate(ConstantState& state) {
    state.iteration = ++iteration;

    if (iteration == 1) {// allocate memory
      // num_nodes is incremented because IDs are 0-based.
      state.num_nodes = ++num_nodes;
      // Allocating space can't be parallelized.
      node_component.set_size(num_nodes);
      for (long i = 0; i < num_nodes; ++ i)
        node_component(i) = i;
        
      return true;
    } else {
      return connections > 0 && iteration < kIterations + 1;
    }
  }
  // Finalize does nothing
  void Finalize() {}

  bool GetNextResult(<?php 
    echo typed_ref_args($outputs_);
    ?>
) {
    // should iterate is true
    if (connections > 0 && iteration < kIterations + 1)
      return false;
    
    if(output_iterator < num_nodes){
      node = output_iterator++;
      component = node_component(node);
      return true;
    }else{
      return false;
    }
  }
    
};

// Initialize the static member types.
arma::rowvec <?php 
    echo $className;
    ?>
::node_component;

<?php 
    return ['kind' => 'GLA', 'name' => $className, 'system_headers' => $sys_headers, 'user_headers' => $user_headers, 'lib_headers' => $lib_headers, 'libraries' => $libraries, 'properties' => $properties, 'extra' => $extra, 'iterable' => true, 'input' => $inputs, 'output' => $outputs, 'result_type' => $result_type, 'generated_state' => $constantState];
}
Ejemplo n.º 23
0
function Contains($args, $targs)
{
    grokit_assert(\count($args) == 1, 'Contains supports exactly 1 input, ' . \count($args) . ' given');
    grokit_assert(array_key_exists('values', $targs), 'Contains() requires a "values" template argument');
    $inputName = 'contains_input';
    $inputType = $args[0];
    $boolType = lookupType('base::bool');
    $typename = generate_name('_ContainsType');
    $funcname = generate_name('Contains');
    $sys_headers = ['cstddef'];
    $use_mct = get_default($targs, 'use.mct', false);
    if ($use_mct) {
        $sys_headers[] = 'mct/closed-hash-set.hpp';
        $setType = 'mct::closed_hash_set<' . $inputType . ', KeyHash>';
    } else {
        $sys_headers[] = 'unordered_set';
        $setType = 'std::unordered_set<' . $inputType . ', KeyHash>';
    }
    $values = $targs['values'];
    grokit_assert(is_array($values), 'Contains(): values argument must be an array of strings');
    $quotedValues = [];
    $escapeChars = "\"'\n\r\t\\";
    foreach ($values as $index => $val) {
        grokit_assert(is_string($val), "Contains(): Value at index {$index} is not a string");
        $quotedValues[] = '"' . addcslashes($val, $escapeChars) . '"';
    }
    $nVals = \count($quotedValues);
    ?>

class <?php 
    echo $typename;
    ?>
 {
public:
	struct KeyHash {
		std::size_t operator () (const <?php 
    echo $inputType;
    ?>
 & val) const {
			return static_cast<std::size_t>(Hash(val));
		}
	};

	using Set = <?php 
    echo $setType;
    ?>
;

	// Singleton
	static const <?php 
    echo $typename;
    ?>
 instance;

private:
	static const char* str_values[<?php 
    echo $nVals;
    ?>
];

	Set values;

	<?php 
    echo $typename;
    ?>
():
		values()
	{
		<?php 
    echo $inputType;
    ?>
 temp;
		for( auto str : str_values ) {
			FromString(temp, str);
			values.insert(temp);
		}
	}

public:
	bool exists(const <?php 
    echo $inputType;
    ?>
 & <?php 
    echo $inputName;
    ?>
) const {
		return values.count(<?php 
    echo $inputName;
    ?>
) > 0;
	}
};

const <?php 
    echo $typename;
    ?>
 <?php 
    echo $typename;
    ?>
::instance;
const char* <?php 
    echo $typename;
    ?>
::str_values[<?php 
    echo $nVals;
    ?>
] = {
	<?php 
    echo implode(", ", $quotedValues);
    ?>
	
};

<?php 
    echo $boolType;
    ?>
 <?php 
    echo $funcname;
    ?>
(const <?php 
    echo $inputType;
    ?>
 & <?php 
    echo $inputName;
    ?>
) {
	return <?php 
    echo $typename;
    ?>
::instance.exists(<?php 
    echo $inputName;
    ?>
);
}

<?php 
    return ['kind' => 'FUNCTION', 'name' => $funcname, 'input' => $args, 'result' => $boolType, 'determinstic' => true, 'system_headers' => $sys_headers];
}
Ejemplo n.º 24
0
/**
 *  A GLA that estimates the cardinality of a dataset using the HyperLogLog
 *  algorithm, with a configurable number of bins.
 */
function HyperLogLog(array $t_args, array $input, array $output)
{
    $debug = get_default($t_args, 'debug', 0);
    grokit_assert(\count($output) == 1, 'HyperLogLog produces only 1 value, ' . \count($output) . ' outputs given.');
    $outputName = array_keys($output)[0];
    $outputType = array_get_index($output, 0);
    if (is_null($outputType)) {
        $outputType = lookupType('BASE::BIGINT');
    }
    $output[$outputName] = $outputType;
    grokit_assert($outputType->is('numeric'), 'BloomFilter output must be numeric!');
    $exp = get_first_key_default($t_args, ['bins.exponent'], 4);
    grokit_assert(is_integer($exp), 'HyperLogLog bins.exponent must be an integer');
    // Set limit of 2^24 bins, because states past 16MB start to get silly
    grokit_assert($exp >= 4 && $exp < 24, 'HyperLogLog bins.exponent must be in range [4, 24]');
    $useBuiltinCtz = get_default($t_args, 'use.builtin.ctz', true);
    $ctzFunc = $useBuiltinCtz ? '__builtin_ctzl' : 'ctz';
    $bins = pow(2, $exp);
    // Determine the value of alpha based on $exp
    switch ($exp) {
        case 4:
            $alpha = 0.673;
            break;
        case 5:
            $alpha = 0.697;
            break;
        case 6:
            $alpha = 0.709;
            break;
        default:
            $alpha = 0.7213000000000001 / (1 + 1.079 / $bins);
    }
    $className = generate_name('HyperLogLog');
    ?>

class <?php 
    echo $className;
    ?>
 {
    // Number of bins for registers
    static constexpr const size_t NUM_BINS = <?php 
    echo $bins;
    ?>
;
    // Number of bits used to index into registers, log2(NUM_BINS)
    static constexpr const size_t INDEX_BITS = <?php 
    echo $exp;
    ?>
;
    // Mask used to obtain register index from hash value
    static constexpr const size_t INDEX_MASK = NUM_BINS - 1;

    // Alpha coefficient used to correct cardinality estimate. Based on NUM_BINS.
    static constexpr const long double ALPHA = <?php 
    echo $alpha;
    ?>
;

    // Value of cardinality estimate after which we must apply the
    // large range correction
    static constexpr const long double LARGE_BREAKPOINT = (1.0 / 30.0) * <?php 
    echo pow(2, 32);
    ?>
;

    // Constants for population count
    static constexpr const uint64_t m1  = 0x5555555555555555;
    static constexpr const uint64_t m2  = 0x3333333333333333;
    static constexpr const uint64_t m4  = 0x0f0f0f0f0f0f0f0f;
    static constexpr const uint64_t h01 = 0x0101010101010101;

    // The registers
    std::array<unsigned char, NUM_BINS> registers;

    // A count used to remember how many tuples were processed, mostly for debugging.
    size_t count;

public:

    <?php 
    echo $className;
    ?>
(void) : registers() {
        for( auto & elem : registers ) {
            elem = 0;
        }
    }

    ~<?php 
    echo $className;
    ?>
() { }

    int popcount(uint64_t x) {
        // Put count of each 2 bits into those 2 bits
        x -= (x >> 1) & m1;
        // Put count of each 4 bits into those 4 bits
        x = (x & m2) + ((x >> 2) & m2);
        // Put count of each 8 bits into those 8 bits
        x  = (x + (x >> 4)) & m4;
        // Returns left 8 bits of x + (x << 8) + (x << 16) + ...
        return (x * h01) >> 56;
    }

    int ctz(int64_t x) {
        return popcount((x & -x) - 1);
    }

    void AddItem( <?php 
    echo const_typed_ref_args($input);
    ?>
 ) {
        count++;

        uint64_t hashVal = H_b;
<?php 
    foreach ($input as $name => $type) {
        ?>
        hashVal = CongruentHash(Hash(<?php 
        echo $name;
        ?>
), hashVal);
<?php 
    }
    // for each input
    ?>

        const size_t registerIndex = hashVal & INDEX_MASK;
        uint64_t value = hashVal >> INDEX_BITS;
        unsigned char nZeros = <?php 
    echo $ctzFunc;
    ?>
(value);

        unsigned char & registerValue = registers[registerIndex];
        registerValue = registerValue > nZeros ? registerValue : nZeros;
    }

    void AddState( <?php 
    echo $className;
    ?>
 & other ) {
        for( size_t i = 0; NUM_BINS > i; i++ ) {
            unsigned char & rVal = registers[i];
            unsigned char & oVal = other.registers[i];
            rVal = rVal > oVal ? rVal : oVal;
        }
    }

    void GetResult( <?php 
    echo $outputType;
    ?>
 & <?php 
    echo $outputName;
    ?>
 ) {
        // Compute harmonic sum of registers and correct by alpha
        long double cardEst = 0;
        size_t nZeroRegisters = 0;
        for( auto elem : registers ) {
            long double power = - static_cast<long double>(elem);
            cardEst += std::pow(2.0, power);

            if( elem == 0 )
                nZeroRegisters++;
        }
        const long double nBins = static_cast<long double>(NUM_BINS);
        const long double zeroBins = static_cast<long double>(nZeroRegisters);

        cardEst = 1 / cardEst;
        cardEst *= ALPHA * nBins * nBins;

        long double cardinality = cardEst;

        if( (cardEst < 2.5 * NUM_BINS) ) { //>
            // Possible small range correction
            if( nZeroRegisters > 0 ) {
                // Small range correction
                cardinality = nBins * std::log(nBins / zeroBins);
            }
        }
        // TODO: Figure out if the large range correction is needed for 64-bit
        // hashes.

        <?php 
    echo $outputName;
    ?>
 = cardinality;
    }
};
<?php 
    $system_headers = ['cmath', 'array', 'cinttypes'];
    if ($debug > 0) {
        $system_headers[] = 'iostream';
    }
    return ['kind' => 'GLA', 'name' => $className, 'input' => $input, 'output' => $output, 'result_type' => 'single', 'user_headers' => ['HashFunctions.h'], 'system_headers' => $system_headers];
}
Ejemplo n.º 25
0
function Join($t_args, $inputs, $outputs, $states)
{
    // Class name randomly generated
    $className = generate_name('Join');
    // Processing of states;
    $states_ = array_combine(['mapping'], $states);
    // Processing of outputs.
    $values = $states_['mapping']->get('vals');
    $outputs = array_combine(array_keys($outputs), $values);
    $sys_headers = ['map', 'tuple'];
    $user_headers = [];
    $lib_headers = [];
    $libraries = [];
    $properties = ['list'];
    $extra = [];
    $result_type = ['multi'];
    ?>

class <?php 
    echo $className;
    ?>
;

<?php 
    $constantState = lookupResource("Join_Constant_State", ['className' => $className, 'states' => $states]);
    ?>

class <?php 
    echo $className;
    ?>
 {
 private:
  using ConstantState = <?php 
    echo $constantState;
    ?>
;
  using Mapping = ConstantState::Mapping;
  using Iter = Mapping::Map::const_iterator;

  // The GroupBy containing the hash.
  const <?php 
    echo $constantState;
    ?>
& constant_state;

  // The iterator used for the multi return.
  Iter it, end;

 public:
  <?php 
    echo $className;
    ?>
(const <?php 
    echo $constantState;
    ?>
& state)
      : constant_state(state) {
  }

  void ProcessTuple(<?php 
    echo const_typed_ref_args($inputs);
    ?>
) {
    auto key = Mapping::ChainHash(<?php 
    echo args($inputs);
    ?>
);
    auto pair = constant_state.map.equal_range(key);
    it = pair.first;
    end = pair.second;
  }

  bool GetNextResult(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
    if (it == end)
      return false;
<?php 
    foreach (array_keys($outputs) as $index => $name) {
        ?>
    <?php 
        echo $name;
        ?>
 = std::get<<?php 
        echo $index;
        ?>
>(it->second);
<?php 
    }
    ?>
    ++it;
    return true;
  }
};

<?php 
    return ['kind' => 'GT', 'name' => $className, 'system_headers' => $sys_headers, 'user_headers' => $user_headers, 'lib_headers' => $lib_headers, 'libraries' => $libraries, 'input' => $inputs, 'output' => $outputs, 'result_type' => 'multi', 'generated_state' => $constantState];
}
Ejemplo n.º 26
0
<?php

$root_node_name = $_POST['xml_root_node_name'];
$record_node_name = $_POST['xml_record_node_name'];
echo "<{$root_node_name}>";
for ($row = 1; $row <= $g_numResults; $row++) {
    echo "\t<{$record_node_name}>\n";
    foreach ($template as $col) {
        echo "\t\t<{$col[0]}>";
        // display the appropriate thing, based on the data type
        switch ($col[1]) {
            case "Name":
                echo generate_name($col[2][0], $g_male_names, $g_female_names, $g_names, $g_surnames);
                break;
            case "Phone":
                echo generate_random_num_str($col[2][0]);
                break;
            case "Email":
                echo generate_email_address($g_words);
                break;
            case "Street-Address":
                echo generate_street_address($g_words);
                break;
            case "City":
                echo $g_cities[rand(0, count($g_cities) - 1)];
                break;
            case "Postal-Zip":
                $wants_canada_postal = $col[2][0];
                $wants_nl_postcode = $col[2][1];
                $wants_uk_postcode = $col[2][2];
                $wants_us_zip = $col[2][3];
Ejemplo n.º 27
0
function CCompUnionFindLPFrag($t_args, $inputs, $outputs)
{
    // Class name is randomly generated.
    $className = generate_name('CCompUnionFindLPFrag');
    // Initializiation of argument names.
    $inputs_ = array_combine(['s', 't'], $inputs);
    $vertex = $inputs_['s'];
    // Construction of outputs.
    $outputs_ = ['node' => $vertex, 'component' => lookupType('base::BIGINT')];
    $outputs = array_combine(array_keys($outputs), $outputs_);
    $sys_headers = ['armadillo', 'algorithm'];
    $user_headers = [];
    $lib_headers = [];
    $libraries = ['armadillo'];
    $properties = [];
    $extra = [];
    $result_type = ['fragment'];
    ?>

using namespace arma;
using namespace std;

class <?php 
    echo $className;
    ?>
;

<?php 
    $constantState = lookupResource('graph::CCompUnionFindLPFrag_Constant_State', ['className' => $className]);
    ?>

class <?php 
    echo $className;
    ?>
 {
 public:
  // The constant state for this GLA.
  using ConstantState = <?php 
    echo $constantState;
    ?>
;
   // The current and final indices of the result for the given fragment.
  using Iterator = std::pair<uint64_t, uint64_t>;

  // The number of iterations to perform, not counting the initial set-up.
  static const constexpr int kIterations = 10;

  // The work is split into chunks of this size before being partitioned.
  static const constexpr int kBlock = 32;

  // The maximum number of fragments to use.
  static const constexpr int kMaxFragments = 64;

 private:
  
  // Node Component
  static arma::rowvec node_component;
  // keep track of component size
  static arma::rowvec component_size;

  // The typical constant state for an iterable GLA.
  const ConstantState& constant_state;

  // The number of unique nodes seen.
  uint64_t num_nodes;

  // The current iteration.
  int iteration;
  
  // The number of fragmetns for the result.
  int num_fragments;

  // check if need more iterations
  uint64_t connections;

 public:
  <?php 
    echo $className;
    ?>
(const <?php 
    echo $constantState;
    ?>
& state)
      : constant_state(state),
        num_nodes(state.num_nodes),
        iteration(state.iteration),connections(0) {
  }

  uint64_t Find(uint64_t node_id){
    // use path compression here
    while (node_id != node_component(node_id)){
        node_component(node_id) = node_component(node_component(node_id));
        node_id = node_component(node_id);
    }
    return node_id;
  }
  
  void Union(uint64_t pid, uint64_t qid){
    // find their root
    pid = Find(pid);
    qid = Find(qid);
    if (pid == qid)
      return;

    ++ connections;
    uint64_t psz = component_size(pid), qsz = component_size(qid);
    if (psz > qsz){
      node_component(qid) = pid;
      component_size(pid) += qsz; 
    }else{
      node_component(pid) = qid;
      component_size(qid) += psz; 
    }
  }

  // Basic dynamic array allocation.
  void AddItem(<?php 
    echo const_typed_ref_args($inputs_);
    ?>
) {
    if (iteration == 0) {
      num_nodes = max((uint64_t) max(s, t), num_nodes);
      return;
    } else{
      Union((uint64_t) s, (uint64_t) t);
    }
  }

  // Hashes are merged.
  void AddState(<?php 
    echo $className;
    ?>
 &other) {
    if (iteration == 0)
      num_nodes = max(num_nodes, other.num_nodes);
    else
      connections += other.connections;
  }

  // Most computation that happens at the end of each iteration is parallelized
  // by performed it inside Finalize.
  bool ShouldIterate(ConstantState& state) {
    state.iteration = ++iteration;
    printf("Entering ShouldIterate. connections: %lu, iteration: %d\n", connections, iteration);
    if (iteration == 1) {// allocate memory
      // num_nodes is incremented because IDs are 0-based.
      state.num_nodes = ++num_nodes;
      // Allocating space can't be parallelized.
      node_component.set_size(num_nodes);
      for (uint64_t i = 0; i < num_nodes; ++ i){
        node_component(i) = i;
      }
      component_size.set_size(num_nodes);
      component_size.fill(1);
      return true;
    } else {
      return connections > 0 && iteration < kIterations + 1;
    }
  }

   int GetNumFragments() {
    uint64_t size = (num_nodes - 1) / kBlock + 1;  // num_nodes / kBlock rounded up.
    num_fragments = (iteration == 0) ? 0 : min(size, (uint64_t) kMaxFragments);
    printf("num_nodes: %lu, size: %lu, num_fragments: %d\n", num_nodes, size, num_fragments);
    return num_fragments;
  }

  // Finalize does nothing
  Iterator* Finalize(int fragment) {
    uint64_t count = num_nodes;
    // The ordering of operations is important. Don't change it.
    uint64_t first = fragment * (count / kBlock) / num_fragments * kBlock;
    uint64_t final = (fragment == num_fragments - 1)
              ? count - 1
              : (fragment + 1) * (count / kBlock) / num_fragments * kBlock - 1;
    
    printf("fragment: %lu\tcount: %lu\tfirst: %lu\tfinal: %lu\n", fragment, count, first, final);
    return new Iterator(first, final);
  }

  bool GetNextResult(Iterator* it, <?php 
    echo typed_ref_args($outputs_);
    ?>
) {
    // should iterate is true
    if (connections > 0 && iteration < kIterations + 1){
      printf("I need more iterations, because connections: %lu, iteration: %d\n", connections, iteration);
      return false;
    }
    if (it->first > it->second)
      return false;
    
    node = it->first++;
    component = Find(node);
    return true;
  }
    
};

// Initialize the static member types.
arma::rowvec <?php 
    echo $className;
    ?>
::node_component;
arma::rowvec <?php 
    echo $className;
    ?>
::component_size;
typedef <?php 
    echo $className;
    ?>
::Iterator <?php 
    echo $className;
    ?>
_Iterator;

<?php 
    return ['kind' => 'GLA', 'name' => $className, 'system_headers' => $sys_headers, 'user_headers' => $user_headers, 'lib_headers' => $lib_headers, 'libraries' => $libraries, 'properties' => $properties, 'extra' => $extra, 'iterable' => true, 'input' => $inputs, 'output' => $outputs, 'result_type' => $result_type, 'generated_state' => $constantState];
}
Ejemplo n.º 28
0
/**
 * A fixed-size typed array view on top of memory. The view is read-only
 *
 * This is used to prevent copying of data when extracting from a column.
 */
function FixedArrayView(array $t_args)
{
    $constructors = [];
    $methods = [];
    $functions = [];
    $globalContent = '';
    grokit_assert(array_key_exists('type', $t_args), 'FixedArrayView: No type given.');
    grokit_assert(array_key_exists('size', $t_args), 'FixedArrayView: No size given');
    $type = $t_args['type'];
    $size = $t_args['size'];
    if (is_array($type)) {
        $type = call_user_func_array('lookupType', $type);
    } else {
        $type = $type->lookup();
    }
    grokit_assert(is_datatype($type), 'arrayView: [type] argument must be a valid datatype.');
    grokit_assert($type->isFixedSize(), 'FixedArray: variable-sized types not supported');
    grokit_assert(is_int($size), 'FixedArrayView: [size] argument must be an integer');
    grokit_assert($size > 0, 'FixedArrayView: [size] arugment must be a positive number.');
    $className = generate_name('FixedArrayView_' . $size . '_');
    ?>
struct <?php 
    echo $className;
    ?>
 {
	using value_type             = <?php 
    echo $type;
    ?>
;
    using size_type              = std::size_t;
    using difference_type        = std::ptrdiff_t;

    using reference              = value_type &;
    using const_reference        = const value_type &;
    using pointer                = value_type *;
    using const_pointer          = const value_type *;
    using iterator               = value_type *;
    using const_iterator         = const value_type *;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

	static constexpr const size_type SIZE = <?php 
    echo $size;
    ?>
;

    const_pointer __elems_;

	<?php 
    echo $className;
    ?>
(): __elems_(nullptr) { }

	// Constructor from externally managed memory
	<?php 
    echo $className;
    ?>
(const_pointer ptr): __elems_(ptr) { }

	// Default copy and move constructors/assignment
	<?php 
    echo $className;
    ?>
(const <?php 
    echo $className;
    ?>
 &other) = default;
	<?php 
    echo $className;
    ?>
 & operator=(const <?php 
    echo $className;
    ?>
 &other) = default;
	<?php 
    echo $className;
    ?>
(<?php 
    echo $className;
    ?>
 &&other) = default;
	<?php 
    echo $className;
    ?>
 & operator=(<?php 
    echo $className;
    ?>
 &&other) = default;

	/***** Element Access *****/

<?php 
    $methods[] = ['at', ['base::BIGINT'], $type->value(), true];
    ?>
    const_reference at( size_type pos ) const {
        if( size() <= pos ) {
            std::ostringstream ss;
            ss  << "Element access out of range:"
                << " size=" << size()
                << " index=" << pos;

             throw std::out_of_range(ss.str());
        }
        return __elems_[pos];
    }

    const_reference operator[]( size_type pos ) const {
        return __elems_[pos];
    }

<?php 
    $methods[] = ['front', [], $type->value(), true];
    ?>
    const_reference front() const {
        return __elems_[0];
    }

<?php 
    $methods[] = ['back', [], $type->value(), true];
    ?>
    const_reference back() const {
        return __elems_[SIZE-1];
    }

    const_pointer data() const noexcept {
        return __elems_;
    }

	/***** Iterators *****/

    const_iterator cbegin() const noexcept {
        return __elems_;
    }

    const_iterator begin() const noexcept {
        return cbegin();
    }

    const_iterator cend() const noexcept {
        return __elems_ + size();
    }

    const_iterator end() const noexcept {
        return cend();
    }

    const_reverse_iterator crbegin() const noexcept {
        return const_reverse_iterator(cend());
    }

    const_reverse_iterator rbegin() const noexcept {
        return crbegin();
    }

    const_reverse_iterator crend() const noexcept {
        return const_reverse_iterator(cbegin());
    }

    const_reverse_iterator rend() const noexcept {
        return crend();
    }

	/***** Capacity *****/

<?php 
    $methods[] = ['empty', [], 'base::bool', true];
    ?>
    bool empty() const noexcept {
        return SIZE == 0;
    }

<?php 
    $methods[] = ['size', [], 'base::BIGINT', true];
    ?>
    size_type size() const noexcept {
        return SIZE;
    }

    size_type max_size() const noexcept {
        return SIZE;
    }

    /***** Operations *****/

    void swap( <?php 
    echo $className;
    ?>
 & other ) noexcept {
        std::swap( __elems_, other.__elems_ );
    }

    /***** EXTENTIONS *****/

    void from_memory( const_pointer mem ) {
        __elems_ = mem;
    }
};

<?php 
    ob_start();
    ?>

inline
bool operator == ( const @type & lhs, const @type & rhs ) {
	// Fast-track for views referring to the same memory
	if (lhs.__elems_ == rhs.__elems_)
		return true;

    for( @type::size_type i = 0; i < @type::SIZE; i++ ) {
        if( lhs[i] != rhs[i] ) return false;
    }
    return true;
}

inline
bool operator != ( const @type & lhs, const @type & rhs ) {
	// Fast-track for views referring to the same memory
	if (lhs.__elems_ == rhs.__elems_)
		return false;

    for( @type::size_type i = 0; i < @type::SIZE; i++ ) {
        if( lhs[i] != rhs[i] ) return true;
    }
    return false;
}

inline
bool operator < ( const @type & lhs, const @type & rhs ) {
    return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
}

inline
bool operator > ( const @type & lhs, const @type & rhs ) {
    return rhs < lhs;
}

inline
bool operator <= ( const @type & lhs, const @type & rhs ) {
    return !(lhs > rhs);
}

inline
bool operator >=( const @type & lhs, const @type & rhs ) {
    return !(lhs < rhs);
}

// ostream operator for easier debugging.
template<class CharT, class Traits = std::char_traits<CharT>>
std::basic_ostream<CharT, Traits>& operator << ( std::basic_ostream<CharT, Traits> & os, const @type s ) {
    std::ostringstream ss;
    bool first = true;
    ss << "[";

    for( const auto & elem : s ) {
        if( first ) {
            first = false;
        } else {
            ss << ", ";
        }

        ss << elem;
    }

    ss << "]";

    os << ss.str();
    return os;
}

template<>
inline
std::size_t SizeFromBuffer<@type>(const char *buffer) {
	return @type::SIZE * sizeof(@type::value_type);
}

template<>
inline
std::size_t SerializedSize(const @type& from) {
	return @type::SIZE * sizeof(@type::value_type);
}

template<>
inline
std::size_t Serialize(char *buffer, const @type &from) {
	@type::pointer ptr = reinterpret_cast<@type::pointer>(buffer);
	std::copy(from.cbegin(), from.cend(), ptr);
	return SerializedSize(from);
}

template<>
inline
std::size_t Deserialize(const char *buffer, @type &dest) {
	@type::const_pointer ptr = reinterpret_cast<@type::const_pointer>(buffer);
	dest.from_memory(ptr);
	return SizeFromBuffer<@type>(buffer);
}

inline
void ToJson( const @type & src, Json::Value & dest ) {
    dest = Json::Value(Json::arrayValue);
    for( @type::const_reference elem : src ) {
        Json::Value tmp;
        ToJson( elem, tmp );
        dest.append(tmp);
    }
}

inline
int ToString( const @type & x, char * buffer ) {
<?php 
    if ($size > 0) {
        ?>
    char * start = buffer;
    char * current = start;

    for( const auto & val : x ) {
        current += ToString( val, current );

        // Replace null with space
        *(current-1) = ' ';
    }

    // Replace final comma with null
    *(current-1) = '\0';

    return current - start;
<?php 
    } else {
        // if size > 0
        ?>
    buffer[0] = '\0';

    return 1;
<?php 
    }
    // if size == 0
    ?>
}

<?php 
    $functions[] = ['Hash', ['@type'], 'BASE::BIGINT', true, true];
    ?>
template<>
inline
uint64_t Hash( const @type & val ) {
    uint64_t hashVal = H_b;
    for( @type::const_reference elem : val ) {
        hashVal = CongruentHash(Hash(elem), hashVal);
    }
    return hashVal;
}

namespace std {

#ifdef _HAS_STD_HASH

// C++11 STL-compliant hash struct specialization
template <>
class hash<@type> {
public:
    size_t operator () (const @type& key) const {
        return Hash(key);
    }
};
#endif // _HAS_STD_HASH

// std::swap specializations

inline
void swap( @type& lhs, @type& rhs ) {
    lhs.swap(rhs);
}

}


<?php 
    $globalContent .= ob_get_clean();
    ?>

<?php 
    $innerDesc = function ($var, $myType) use($type) {
        $describer = $type->describer('json');
        ?>
        <?php 
        echo $var;
        ?>
["size"] = Json::Int64(<?php 
        echo $myType;
        ?>
::SIZE);
<?php 
        $innerVar = "{$var}[\"inner_type\"]";
        $describer($innerVar, $type);
    };
    $sys_headers = ['iterator', 'algorithm', 'stdexcept', 'utility', 'cstdint', 'cstddef', 'iostream', 'sstream', 'cstring'];
    $user_headers = ['Config.h'];
    $extras = ['size' => $size, 'type' => $type];
    $sizeBytes = $size * $type->get('size.bytes');
    $extras['size.bytes'] = $sizeBytes;
    return ['kind' => 'TYPE', 'name' => $className, 'system_headers' => $sys_headers, 'user_headers' => $user_headers, 'constructors' => $constructors, 'methods' => $methods, 'functions' => $functions, 'binary_operators' => ['==', '!=', '<', '>', '<=', '>='], 'global_content' => $globalContent, 'complex' => "ColumnIterator<@type, 0, {$sizeBytes}>", 'properties' => ['container', 'sequence', 'array-view'], 'extras' => $extras, 'describe_json' => DescribeJson('array', $innerDesc)];
}
Ejemplo n.º 29
0
 function copyRecord($tableName, $field_id, $field_name, $record_id, $key = '', $listFieldFile = '', $filePath = '')
 {
     $arrayFile = explode(",", $listFieldFile);
     $strupdate = '';
     global $medium_width;
     global $medium_heght;
     global $medium2_heght;
     global $medium2_width;
     global $small_width;
     global $small_heght;
     if ($listFieldFile != '') {
         $db_file = new db_query("SELECT " . $listFieldFile . " FROM " . $tableName . " WHERE " . $field_id . "=" . $record_id . " LIMIT 1");
         if ($row = mysqli_fetch_array($db_file->result)) {
             foreach ($arrayFile as $key => $value) {
                 if ($row[$value] != '') {
                     if (file_exists($filePath . $row[$value])) {
                         $newfile = generate_name($row[$value]);
                         @copy($filePath . $row[$value], $filePath . $newfile);
                         @copy($filePath . 'small_' . $row[$value], $filePath . 'small_' . $newfile);
                         @copy($filePath . 'medium_' . $row[$value], $filePath . 'medium_' . $newfile);
                         @copy($filePath . 'medium2_' . $row[$value], $filePath . 'medium2_' . $newfile);
                         $strupdate .= "," . $value . " = '" . $newfile . "'";
                     }
                 }
             }
         }
     }
     $db_record = new db_execute("DROP TABLE IF EXISTS temp_" . $tableName);
     $db_record = new db_execute("CREATE table temp_" . $tableName . " SELECT * FROM " . $tableName . " WHERE " . $field_id . " = " . $record_id);
     if ($key != '') {
         $db_record = new db_execute("update temp_" . $tableName . " SET " . $key . " = (select MAX(" . $key . ") FROM " . $tableName . ")+1 WHERE " . $field_id . " = " . $record_id);
     }
     $db_record = new db_query("SELECT MAX(" . $field_id . ") AS idmax FROM " . $tableName);
     $newid = 0;
     if ($row = mysqli_fetch_assoc($db_record->result)) {
         $newid = intval($row["idmax"]) + 1;
     }
     $reFieldName = $field_name != '' ? "," . $field_name . " = CONCAT(''," . $field_name . ")" : '';
     $reFieldName .= $strupdate;
     $db_record = new db_query("UPDATE temp_" . $tableName . " SET " . $field_id . "=" . $newid . $reFieldName . " WHERE " . $field_id . "=" . $record_id);
     $db_record = new db_execute("INSERT INTO " . $tableName . " SELECT * FROM temp_" . $tableName . " WHERE " . $field_id . " = " . $newid);
     $db_record = new db_execute("DROP TABLE IF EXISTS temp_" . $tableName);
     unset($db_record);
     return $newid;
 }
Ejemplo n.º 30
0
function ConnectedComponents(array $t_args, array $inputs, array $outputs)
{
    // Class name is randomly generated
    $className = generate_name("CCompGLA");
    // Processing of inputs.
    grokit_assert(count($inputs) == 2, 'Connected Components: 2 inputs expected');
    $inputs_ = array_combine(['src', 'dst'], $inputs);
    // Setting output type
    $outType = lookupType('int');
    $outputs_ = ['node' => $outType, 'component' => $outType];
    $outputs = array_combine(array_keys($outputs), $outputs_);
    $sys_headers = ["vector", "mct/hash-map.hpp"];
    $user_headers = [];
    $lib_headers = [];
    ?>

using namespace std;

class <?php 
    echo $className;
    ?>
;

class <?php 
    echo $className;
    ?>
 {
 
 class UnionFindMap{
  private:
    mct::closed_hash_map<uint64_t, uint64_t>* parent; 
    mct::closed_hash_map<uint64_t, uint64_t> sz;

    const uint64_t NON_EXISTING_ID = -1;
  public:
    // constructor did nothing
    UnionFindMap(){
      parent = new mct::closed_hash_map<uint64_t, uint64_t>();
    }


    uint64_t Find(uint64_t i){
      if ((*parent).find(i) == (*parent).end()){
        return NON_EXISTING_ID;
      }
      // use path compression here
      while (i != (*parent)[i]){
        (*parent)[i] = (*parent)[(*parent)[i]];
        i = (*parent)[i];
      }
      return i;
    }

    // put merge small tree into higher tree
    // if disjoint, merge and return false
    void Union(uint64_t i, uint64_t j){
      uint64_t ip = Find(i);
      uint64_t jp = Find(j);

      if (ip != NON_EXISTING_ID && jp != NON_EXISTING_ID){// both exists
        if (ip != jp){
          if (sz[ip] < sz[jp]){
            (*parent)[ip] = jp; sz[jp] += sz[ip];
          }else{
            (*parent)[jp] = ip; sz[ip] += sz[jp];
          }
        }
      }else if(ip == NON_EXISTING_ID && jp == NON_EXISTING_ID){// both new
        (*parent)[i] = i; sz[i] = 2;
        (*parent)[j] = i; 
      }else if (jp == NON_EXISTING_ID){ // i exists
        (*parent)[j] = ip; sz[ip] ++;
      }else{
        (*parent)[i] = jp; sz[jp] ++;
      }
    }

    mct::closed_hash_map<uint64_t, uint64_t>* GetUF(){
      return parent;
    }

    bool IsEmpty(){
      return (*parent).empty();
    }

    uint64_t GetSize(){
      return (uint64_t) (*parent).size(); 
    }

    void SetData(mct::closed_hash_map<uint64_t, uint64_t>* other_data){
      parent = other_data;
    }

    // 
    void FinalizeRoot(){
      for(mct::closed_hash_map<uint64_t, uint64_t>::iterator it = (*parent).begin(); it != (*parent).end(); ++ it){
        it->second = Find(it->first);
      }
    }

    void Clear(){
      (*parent).clear();
      sz.clear();
    }
    
    ~UnionFindMap(){
        delete parent;
    }

 };

 private:
  // union-find map data structure, which contains nodeID->compID information
  UnionFindMap primary_uf;
  mct::closed_hash_map<uint64_t, uint64_t>::iterator output_iterator, output_iterator_end;
  bool localFinalized = false;
 public:
  <?php 
    echo $className;
    ?>
() {}

  void AddItem(<?php 
    echo const_typed_ref_args($inputs_);
    ?>
) {
    uint64_t src_ = Hash(src);
    uint64_t dst_ = Hash(dst);
  
    primary_uf.Union(src_, dst_);
  }

  void AddState(<?php 
    echo $className;
    ?>
 &other) {
      FinalizeLocalState();
      other.FinalizeLocalState();
      mct::closed_hash_map<uint64_t, uint64_t>* this_state_data = primary_uf.GetUF();
      mct::closed_hash_map<uint64_t, uint64_t>* other_state_data = other.primary_uf.GetUF();

      if (primary_uf.GetSize() < other.primary_uf.GetSize()){
        mct::closed_hash_map<uint64_t, uint64_t>* tmp = this_state_data;
        this_state_data = other_state_data;
        other_state_data = tmp;

        primary_uf.SetData(this_state_data);
        other.primary_uf.SetData(other_state_data);
      }
      assert(primary_uf.GetSize() >= other.primary_uf.GetSize());
      
      UnionFindMap secondary_uf;
      //go over the other state, and maintain a secondary table
      for(auto const& entry:(*other_state_data)){
        if ((*this_state_data).count(entry.first) == 1){// key exists in this state
          uint64_t this_comp_id = (*this_state_data)[entry.first];
          if (this_comp_id != entry.second) // merge needed
            secondary_uf.Union(this_comp_id, entry.second);
        }else{
          (*this_state_data)[entry.first] = entry.second;
        }
      }

      // check if side table empty
      if (secondary_uf.IsEmpty()){
        return;
      }

      // apply the side table
      secondary_uf.FinalizeRoot();
      mct::closed_hash_map<uint64_t, uint64_t>* secondary_state_data = secondary_uf.GetUF();
      for (auto& p:(*this_state_data)){
        if ((*secondary_state_data).find(p.second) != (*secondary_state_data).end()){
          p.second = (*secondary_state_data)[p.second];
        }
      }
      
  }

  void FinalizeLocalState(){
  	if (!localFinalized){
  		primary_uf.FinalizeRoot();
  		localFinalized = true;
  	}
  }

  void Finalize(){
      output_iterator = primary_uf.GetUF()->begin();
      output_iterator_end = primary_uf.GetUF()->end();
  }

  bool GetNextResult(<?php 
    echo typed_ref_args($outputs_);
    ?>
) {
      
      if (output_iterator != output_iterator_end){
        node = output_iterator->first;
        component = output_iterator->second;
        
        ++ output_iterator;
        return true;
      }else{
        return false;
      }
 }
};

<?php 
    return ['kind' => 'GLA', 'name' => $className, 'system_headers' => $sys_headers, 'user_headers' => $user_headers, 'lib_headers' => $lib_headers, 'input' => $inputs, 'output' => $outputs, 'result_type' => 'multi'];
}