void
run_assign_and_copy_constructor_test(const char *test_name) {
    REMARK("Testing assignment and copy construction for %s\n", test_name);

    // test initializer with exemplar
    T initializer0;
    test_helper<T>::init(initializer0);
    T initializer7;
    test_helper<T>::set(initializer7,7);
    tbb::enumerable_thread_specific<T> create1(initializer7);
    (void) create1.local();  // create an initialized value
    ASSERT(7 == test_helper<T>::get(create1.local()), NULL);

    // test copy construction with exemplar initializer
    create1.clear();
    tbb::enumerable_thread_specific<T> copy1(create1);
    (void) copy1.local();
    ASSERT(7 == test_helper<T>::get(copy1.local()), NULL);

    // test copy assignment with exemplar initializer
    create1.clear();
    tbb::enumerable_thread_specific<T> assign1(initializer0);
    assign1 = create1;
    (void) assign1.local();
    ASSERT(7 == test_helper<T>::get(assign1.local()), NULL);

    // test creation with finit function
    FunctorFinit<T,7> my_finit7(SecretTag);
    tbb::enumerable_thread_specific<T> create2(my_finit7);
    (void) create2.local();
    ASSERT(7 == test_helper<T>::get(create2.local()), NULL);

    // test copy construction with function initializer
    create2.clear();
    tbb::enumerable_thread_specific<T> copy2(create2);
    (void) copy2.local();
    ASSERT(7 == test_helper<T>::get(copy2.local()), NULL);

    // test copy assignment with function initializer
    create2.clear();
    FunctorFinit<T,0> my_finit(SecretTag);
    tbb::enumerable_thread_specific<T> assign2(my_finit);
    assign2 = create2;
    (void) assign2.local();
    ASSERT(7 == test_helper<T>::get(assign2.local()), NULL);
}
bool Circuit::parseLine(std::string line)
{
    std::regex sWire("\\s*(wire|input|output) +(\\w+)\\s*;\\s*");
    std::regex mWire("\\s*(wire|input|output)\\s+\\[(\\d+)\\:(\\d+)\\]\\s*(\\w+)\\s*;\\s*");
    std::regex rGate("\\s*(\\w+)\\s+(\\w+)\\s*\\(\\s*");
    std::regex in1("\\s*.(A)\\((\\w+\\[\\d+\\]|\\w+)\\)\\s*,\\s*");
    std::regex in2("\\s*.(B|D)\\((\\w+\\[\\d+\\]|\\w+)\\)\\s*,\\s*");
    std::regex rOut("\\s*.(Y|Q)\\((\\w+\\[\\d+\\]|\\w+)\\)\\s*");
    std::regex assign1("\\s*assign\\s+(\\w+\\[\\d+\\]|\\w+)\\s+\\=\\s+(\\w+\\[\\d+\\]|\\w+)\\s*;\\s*");
    std::smatch results;
    
    if(std::regex_match(line, results, sWire))
    {
        //std::cout << results.str(1) <<" "<< results.str(2) << std::endl;
        w = new wire(results.str(2), results.str(1));
        if(results.str(1) != "wire")
        {
            g = new gate(results.str(2), results.str(1));
            if(results.str(1) == "input")
            {
                g->setIn1("root");
                g->setOut(results.str(2));
                w->setWSource(g);
                wireMap["root"]->setWDestination(g);
            }
            else
            {
                g->setIn1(results.str(2));
                w->setWDestination(g);
            }
            gateMap.insert(std::pair<std::string, gate*> (results.str(2), g));
        }
        wireMap.insert(std::pair<std::string, wire*> (results.str(2), w));
    }
    else if (std::regex_match(line, results, mWire))
    {
        //std::cout << results.str(1) << " bus " <<results.str(2) << ": "<< results.str(3) << ' '<< results.str(4) << std::endl;
        for(int i = std::atoi(results.str(3).c_str()); i <= std::atoi(results.str(2).c_str()); i++)
        {
            std::string x = results.str(4);
            x += '[' + std::to_string(i) + ']';
            w = new wire(x, results.str(1));
            if(results.str(1) != "wire")
            {
                g = new gate(x, results.str(1));
                if(results.str(1) == "input")
                {
                    g->setIn1("root");
                    g->setOut(x);
                    w->setWSource(g);
                    wireMap["root"]->setWDestination(g);
                    gateMap.insert(std::pair<std::string, gate*> (x, g));
                }
                else
                {
                    g->setIn1(x);
                    w->setWDestination(g);
                }
            }
            wireMap.insert(std::pair<std::string, wire*>(x, w));
        }
    }
    else if (std::regex_match(line, results, rGate))
    {
        pGate2 = pGate = results.str(2);
        //std::cout << "\nGate " << results.str(1) << ' ' <<results.str(2) << std::endl;
        if(results.str(1) == "DFFPOSX1")
        {
            pGate += "_input";
            pGate2 += "_output";
            g = new gate(pGate, results.str(1));
            g->setIn1("root");
            wireMap["root"]->setWDestination(g);
            gateMap.insert(std::pair<std::string, gate*> (pGate, g));
            gateMap[pGate]->setIsFlip(true);
            gateMap[pGate]->setFlipIn(true);
            
            g = new gate(pGate2, results.str(1));
            g->setFlipIn(true);
            gateMap.insert(std::pair<std::string, gate*> (pGate2, g));
            gateMap[pGate2]->setIsFlip(true);
            gateMap[pGate2]->setFlipIn(false);
        }
        else
        {
            g = new gate(results.str(2), results.str(1));
            g->setFlipIn(false);
            gateMap.insert(std::pair<std::string, gate*> (results.str(2), g));
        }
    }
    else if (std::regex_match(line, results, in1))
    {
        //std::cout<<"InputPin1: "<< results.str(2) << std::endl;
        gateMap[pGate2]->setIn1(results.str(2));
        wireMap[results.str(2)]->setWDestination(gateMap[pGate2]);
    }
    else if (std::regex_match(line, results, in2))
    {
        //std::cout<<"InputPin2: "<< results.str(2) << std::endl;
        gateMap[pGate2]->setIn2(results.str(2));
        wireMap[results.str(2)]->setWDestination(gateMap[pGate2]);
    }
    else if (std::regex_match(line, results, rOut))
    {
        //std::cout<<"OutputPin: "<< results.str(2) << std::endl;
        gateMap[pGate]->setOut(results.str(2));
        wireMap[results.str(2)]->setWSource(gateMap[pGate]);
    }
    else if (std::regex_match(line, results, assign1))
    {
        //std::cout<<"Assign: "<< results.str(1) << " to" << results.str(2) <<std::endl;
        wire *temp1, *temp2;
        temp1 = wireMap[results.str(1)];
        temp2 = wireMap[results.str(2)];
        temp1->setAssign(temp2);
    }
    else return false;
    
    return true;
}