<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

#include <string>
#include <png.h>
#include <jpeglib.h>
#include "graphics.hpp"
#include "image_util.hpp"
#include "memory.hpp"

namespace mapnik
{

    //use memory manager for mem allocation in libpng

    png_voidp malloc_fn(png_structp png_ptr,png_size_t size)
    {
        return Object::operator new(size);
    }
    void free_fn(png_structp png_ptr, png_voidp ptr)
    {
        Object::operator delete(ptr);
    }
    //
    void ImageUtils::save_to_file(const std::string& filename,const std::string& type,const Image32& image)
    {
	//all that should go into image_writer factory
        if (type=="png")
        {
            save_as_png(filename,image);
        }
	else if (type=="jpeg")
	{
	    save_as_jpeg(filename,85,image);
	}
    }

    void ImageUtils::save_as_png(const std::string& filename,const Image32& image)
    {
        FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
        png_voidp mem_ptr=0;
        png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
						    (png_voidp)mem_ptr,0, 0);

        if (!png_ptr) return;
        png_set_mem_fn(png_ptr,mem_ptr,malloc_fn,free_fn);

        // switch on optimization
	//#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
        //png_uint_32 mask, flags;

        //flags = png_get_asm_flags(png_ptr);
        //mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
        //png_set_asm_flags(png_ptr, flags | mask);
	//#endif
	png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_write_struct(&png_ptr,(png_infopp)0);
            fclose(fp);
            return;
        }
        if (setjmp(png_jmpbuf(png_ptr)))
        {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            fclose(fp);
            return;
        }

        png_init_io(png_ptr, fp);
	//png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
	//png_set_compression_strategy(png_ptr, Z_FILTERED);
        png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
            PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
        png_write_info(png_ptr, info_ptr);

        const ImageData32& imageData=image.data();

        for (unsigned i=0;i<image.height();i++)
        {
            png_write_row(png_ptr,(png_bytep)imageData.getRow(i));
        }

        png_write_end(png_ptr, info_ptr);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
    }

    void ImageUtils::save_as_jpeg(const std::string& filename,int quality, const Image32& image)
    {
	FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;

	int width=image.width();
	int height=image.height();

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, fp);
	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality,1);
	jpeg_start_compress(&cinfo, 1);
	JSAMPROW row_pointer[1];
	JSAMPLE* row=new JSAMPLE[width*3];
	const ImageData32& imageData=image.data();
	while (cinfo.next_scanline < cinfo.image_height)
	{
	    const unsigned* imageRow=imageData.getRow(cinfo.next_scanline);
	    int index=0;
	    for (int i=0;i<width;++i)
	    {
		row[index++]=(imageRow[i])&0xff;
		row[index++]=(imageRow[i]>>8)&0xff;
		row[index++]=(imageRow[i]>>16)&0xff;
	    }
	    row_pointer[0] = &row[0];
	    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	delete [] row;
	jpeg_finish_compress(&cinfo);
	fclose(fp);
	jpeg_destroy_compress(&cinfo);
    }
}
<commit_msg>switched on optimization in png writing code<commit_after>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

#include <string>
#include <png.h>
#include <jpeglib.h>
#include "graphics.hpp"
#include "image_util.hpp"
#include "memory.hpp"

namespace mapnik
{

    //use memory manager for mem allocation in libpng

    png_voidp malloc_fn(png_structp png_ptr,png_size_t size)
    {
        return Object::operator new(size);
    }
    void free_fn(png_structp png_ptr, png_voidp ptr)
    {
        Object::operator delete(ptr);
    }
    //
    void ImageUtils::save_to_file(const std::string& filename,const std::string& type,const Image32& image)
    {
	//all that should go into image_writer factory
        if (type=="png")
        {
            save_as_png(filename,image);
        }
	else if (type=="jpeg")
	{
	    save_as_jpeg(filename,85,image);
	}
    }

    void ImageUtils::save_as_png(const std::string& filename,const Image32& image)
    {
        FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
        png_voidp mem_ptr=0;
        png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
						    (png_voidp)mem_ptr,0, 0);

        if (!png_ptr) return;
        png_set_mem_fn(png_ptr,mem_ptr,malloc_fn,free_fn);

        // switch on optimization
	#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
        png_uint_32 mask, flags;

        flags = png_get_asm_flags(png_ptr);
        mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
        png_set_asm_flags(png_ptr, flags | mask);
	#endif
	png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_write_struct(&png_ptr,(png_infopp)0);
            fclose(fp);
            return;
        }
        if (setjmp(png_jmpbuf(png_ptr)))
        {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            fclose(fp);
            return;
        }

        png_init_io(png_ptr, fp);
	//png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
	//png_set_compression_strategy(png_ptr, Z_FILTERED);
        png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
            PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
        png_write_info(png_ptr, info_ptr);

        const ImageData32& imageData=image.data();

        for (unsigned i=0;i<image.height();i++)
        {
            png_write_row(png_ptr,(png_bytep)imageData.getRow(i));
        }

        png_write_end(png_ptr, info_ptr);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
    }

    void ImageUtils::save_as_jpeg(const std::string& filename,int quality, const Image32& image)
    {
	FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;

	int width=image.width();
	int height=image.height();

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, fp);
	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality,1);
	jpeg_start_compress(&cinfo, 1);
	JSAMPROW row_pointer[1];
	JSAMPLE* row=new JSAMPLE[width*3];
	const ImageData32& imageData=image.data();
	while (cinfo.next_scanline < cinfo.image_height)
	{
	    const unsigned* imageRow=imageData.getRow(cinfo.next_scanline);
	    int index=0;
	    for (int i=0;i<width;++i)
	    {
		row[index++]=(imageRow[i])&0xff;
		row[index++]=(imageRow[i]>>8)&0xff;
		row[index++]=(imageRow[i]>>16)&0xff;
	    }
	    row_pointer[0] = &row[0];
	    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	delete [] row;
	jpeg_finish_compress(&cinfo);
	fclose(fp);
	jpeg_destroy_compress(&cinfo);
    }
}
<|endoftext|>


<commit_before>#ifndef __clang__

#include <algorithm>

#endif

#include "index_internal.h"
#include "usr.h"

namespace levidb8 {
    static constexpr OffsetToNode _root{0};

    class BitDegradeTree::BitDegradeTreeIterator : public Iterator<Slice, OffsetToData> {
    private:
        const BitDegradeTree * _index;
        USR _usr;
        BDNode _node_clone;
        int _cursor{};
        bool _valid = false;

    public:
        explicit BitDegradeTreeIterator(const BitDegradeTree * index) noexcept : _index(index) {}

        ~BitDegradeTreeIterator() noexcept override = default;

        bool valid() const override {
            return _valid;
        }

        void seekToFirst() override {
            loadToLeftest();
        }

        void seekToLast() override {
            loadToRightest();
        }

        void seek(const Slice & k) override {
            loadToKey(k);
        }

        void seekForPrev(const Slice & k) override { seek(k); }

        void next() override {
            assert(valid());
            if ((++_cursor) >= _node_clone.immut_ptrs().size()
                || _node_clone.immut_ptrs()[_cursor].isNull()
                || _node_clone.immut_ptrs()[_cursor].isNode()) {
                reloadToRight();
            } else {
                configureUsrForNext();
            }
        }

        void prev() override {
            assert(valid());
            if ((--_cursor) < 0
                || _node_clone.immut_ptrs()[_cursor].isNull()
                || _node_clone.immut_ptrs()[_cursor].isNode()) {
                reloadToLeft();
            } else {
                configureUsrForPrev();
            }
        }

        Slice key() const override {
            assert(valid());
            return _usr.toSlice();
        }

        OffsetToData value() const override {
            assert(valid());
            return _node_clone.immut_ptrs()[_cursor].asData();
        }

    private:
        void loadToLeftest() { loadToTarget<false>({}); }

        void loadToRightest() { loadToTarget<true>({}); }

        void loadToKey(const Slice & k) {
            _usr.clear();
            RWLockReadGuard read_guard(&_index->_expand_lock);

            RWLockReadGuard node_read_guard(_index->offToNodeLock(_root));
            const BDNode * cursor = _index->offToMemNode(_root);
            while (true) {
                auto pos = _index->findBestMatch(cursor, k, &_usr);
                size_t idx;
                bool direct;
                std::tie(idx, direct, std::ignore) = pos;

                _cursor = static_cast<int>(idx + direct);
                CritPtr ptr = cursor->immut_ptrs()[_cursor];
                if (ptr.isNull()) {
                    _valid = false;
                    return;
                }
                if (ptr.isNode()) {
                    node_read_guard = RWLockReadGuard(_index->offToNodeLock(ptr.asNode()));
                    cursor = _index->offToMemNode(ptr.asNode());
                } else {
                    _node_clone = *cursor;
                    _valid = true;
                    return;
                }
            }
        }

        void reloadToRight() {
            if (metMax()) {
                _valid = false;
            } else {
                loadToTarget<false>(largerKey());
            }
        }

        void reloadToLeft() {
            if (metMin()) {
                _valid = false;
            } else {
                loadToTarget<true>(smallerKey());
            }
        }

        void configureUsrForNext() noexcept {
            // @formatter:off
#ifndef NDEBUG
            auto pos =
#endif
                    findBestMatch<false>(&_node_clone, largerKey(), &_usr);
#ifndef NDEBUG
            assert(pos.first + pos.second == _cursor);
#endif
            // @formatter:on
        }

        void configureUsrForPrev() noexcept {
            // @formatter:off
#ifndef NDEBUG
            auto pos =
#endif
                    findBestMatch<true>(&_node_clone, smallerKey(), &_usr);
#ifndef NDEBUG
            assert(pos.first + pos.second == _cursor);
#endif
            // @formatter:on
        }

    private:
        template<bool RIGHT_FIRST>
        std::pair<size_t, bool>
        findBestMatch(const BDNode * node, const Slice & target, USR * reveal_info) noexcept {
            const uint32_t * cbegin = node->immut_diffs().cbegin();
            const uint32_t * cend;

            size_t size = node->size();
            if (size <= 1) {
                reveal_info->mut_src().resize(1);
                reveal_info->mut_src().front() = 0;
                reveal_info->mut_extra().resize(1);
                reveal_info->mut_extra().front() = 0;
                return {0, false};
            }
            cend = &node->immut_diffs()[size - 1];

            auto cmp = [node](const uint32_t & a, const uint32_t & b) noexcept {
                return a < b || (a == b && (node->immut_masks()[&a - node->immut_diffs().cbegin()] & ~(1 << 7)) >
                                                   (node->immut_masks()[&b - node->immut_diffs().cbegin()] & ~(1 << 7)));
            };

            while (true) {
                const uint32_t * min_it = std::min_element(cbegin, cend, cmp);
                uint32_t diff_at = *min_it;
                uint8_t trans_mask = transMask(node->immut_masks()[min_it - node->immut_diffs().cbegin()]);

                uint8_t crit_byte = target.size() > diff_at ? charToUint8(target[diff_at])
                                                            : static_cast<uint8_t>(RIGHT_FIRST ? UINT8_MAX : 0);
                auto direct = static_cast<bool>((1 + (crit_byte | trans_mask)) >> 8);
                reveal_info->reveal(diff_at, uint8ToChar(trans_mask), direct);

                if (!direct) { // left
                    cend = min_it;
                } else { // right
                    cbegin = min_it + 1;
                }

                if (cbegin == cend) {
                    return {min_it - node->immut_diffs().cbegin(), direct};
                }
            }
        };

        template<bool RIGHT_FIRST>
        void loadToTarget(const Slice & target) {
            _usr.clear();
            RWLockReadGuard read_guard(&_index->_expand_lock);

            RWLockReadGuard node_read_guard(_index->offToNodeLock(_root));
            const BDNode * cursor = _index->offToMemNode(_root);
            while (true) {
                auto pos = findBestMatch<RIGHT_FIRST>(cursor, target, &_usr);
                size_t idx;
                bool direct;
                std::tie(idx, direct) = pos;

                _cursor = static_cast<int>(idx + direct);
                CritPtr ptr = cursor->immut_ptrs()[_cursor];
                if (ptr.isNull()) {
                    _valid = false;
                    return;
                }
                if (ptr.isNode()) {
                    node_read_guard = RWLockReadGuard(_index->offToNodeLock(ptr.asNode()));
                    cursor = _index->offToMemNode(ptr.asNode());
                } else {
                    _node_clone = *cursor;
                    _valid = true;
                    return;
                }
            }
        }

        Slice smallerKey() const noexcept {
            Slice s = key();
            Slice res;

            size_t i = s.size();
            do {
                --i;
                if ((_usr.immut_extra()[i] & _usr.immut_src()[i]) == 0) {
                    assert(i != 0);
                    continue;
                }

                auto * arr = reinterpret_cast<char *>(malloc(i + 1));
                res = Slice::pinnableSlice(arr, i + 1);
                memcpy(arr, s.data(), res.size());

                --arr[i];
                break;
            } while (true);

            assert(res.owned());
            return res;
        }

        Slice largerKey() const noexcept {
            Slice s = key();
            Slice res;

            size_t i = s.size();
            do {
                --i;
                char xor_res;
                if ((xor_res = (_usr.immut_extra()[i] ^ _usr.immut_src()[i])) == 0) {
                    assert(i != 0);
                    continue;
                }

                auto * arr = reinterpret_cast<char *>(malloc(i + 1));
                res = Slice::pinnableSlice(arr, i + 1);
                memcpy(arr, s.data(), res.size());

                auto n = __builtin_ffs(xor_res);
                arr[i] |= 1 << (n - 1); // 0 to 1
                arr[i] &= uint8ToChar(UINT8_MAX >> (n - 1) << (n - 1));
                break;
            } while (true);

            assert(res.owned());
            return res;
        }

        bool metMin() const noexcept {
            return std::all_of(_usr.immut_src().cbegin(), _usr.immut_src().cend(), [](char a) noexcept {
                return a == 0;
            });
        }

        bool metMax() const noexcept {
            return std::all_of(_usr.immut_src().cbegin(), _usr.immut_src().cend(), [this](const char & a) noexcept {
                return (a ^ _usr.immut_extra()[&a - &_usr.immut_src().front()]) == 0;
            });
        }
    };

    std::unique_ptr<Iterator<Slice/* usr */, OffsetToData>>
    BitDegradeTree::scan() const noexcept {
        return std::make_unique<BitDegradeTreeIterator>(this);
    }
}<commit_msg>coverity[leaked_storage]<commit_after>#ifndef __clang__

#include <algorithm>

#endif

#include "index_internal.h"
#include "usr.h"

namespace levidb8 {
    static constexpr OffsetToNode _root{0};

    class BitDegradeTree::BitDegradeTreeIterator : public Iterator<Slice, OffsetToData> {
    private:
        const BitDegradeTree * _index;
        USR _usr;
        BDNode _node_clone;
        int _cursor{};
        bool _valid = false;

    public:
        explicit BitDegradeTreeIterator(const BitDegradeTree * index) noexcept : _index(index) {}

        ~BitDegradeTreeIterator() noexcept override = default;

        bool valid() const override {
            return _valid;
        }

        void seekToFirst() override {
            loadToLeftest();
        }

        void seekToLast() override {
            loadToRightest();
        }

        void seek(const Slice & k) override {
            loadToKey(k);
        }

        void seekForPrev(const Slice & k) override { seek(k); }

        void next() override {
            assert(valid());
            if ((++_cursor) >= _node_clone.immut_ptrs().size()
                || _node_clone.immut_ptrs()[_cursor].isNull()
                || _node_clone.immut_ptrs()[_cursor].isNode()) {
                reloadToRight();
            } else {
                configureUsrForNext();
            }
        }

        void prev() override {
            assert(valid());
            if ((--_cursor) < 0
                || _node_clone.immut_ptrs()[_cursor].isNull()
                || _node_clone.immut_ptrs()[_cursor].isNode()) {
                reloadToLeft();
            } else {
                configureUsrForPrev();
            }
        }

        Slice key() const override {
            assert(valid());
            return _usr.toSlice();
        }

        OffsetToData value() const override {
            assert(valid());
            return _node_clone.immut_ptrs()[_cursor].asData();
        }

    private:
        void loadToLeftest() { loadToTarget<false>({}); }

        void loadToRightest() { loadToTarget<true>({}); }

        void loadToKey(const Slice & k) {
            _usr.clear();
            RWLockReadGuard read_guard(&_index->_expand_lock);

            RWLockReadGuard node_read_guard(_index->offToNodeLock(_root));
            const BDNode * cursor = _index->offToMemNode(_root);
            while (true) {
                auto pos = _index->findBestMatch(cursor, k, &_usr);
                size_t idx;
                bool direct;
                std::tie(idx, direct, std::ignore) = pos;

                _cursor = static_cast<int>(idx + direct);
                CritPtr ptr = cursor->immut_ptrs()[_cursor];
                if (ptr.isNull()) {
                    _valid = false;
                    return;
                }
                if (ptr.isNode()) {
                    node_read_guard = RWLockReadGuard(_index->offToNodeLock(ptr.asNode()));
                    cursor = _index->offToMemNode(ptr.asNode());
                } else {
                    _node_clone = *cursor;
                    _valid = true;
                    return;
                }
            }
        }

        void reloadToRight() {
            if (metMax()) {
                _valid = false;
            } else {
                loadToTarget<false>(largerKey());
            }
        }

        void reloadToLeft() {
            if (metMin()) {
                _valid = false;
            } else {
                loadToTarget<true>(smallerKey());
            }
        }

        void configureUsrForNext() noexcept {
            // @formatter:off
#ifndef NDEBUG
            auto pos =
#endif
                    findBestMatch<false>(&_node_clone, largerKey(), &_usr);
#ifndef NDEBUG
            assert(pos.first + pos.second == _cursor);
#endif
            // @formatter:on
        }

        void configureUsrForPrev() noexcept {
            // @formatter:off
#ifndef NDEBUG
            auto pos =
#endif
                    findBestMatch<true>(&_node_clone, smallerKey(), &_usr);
#ifndef NDEBUG
            assert(pos.first + pos.second == _cursor);
#endif
            // @formatter:on
        }

    private:
        template<bool RIGHT_FIRST>
        std::pair<size_t, bool>
        findBestMatch(const BDNode * node, const Slice & target, USR * reveal_info) noexcept {
            const uint32_t * cbegin = node->immut_diffs().cbegin();
            const uint32_t * cend;

            size_t size = node->size();
            if (size <= 1) {
                reveal_info->mut_src().resize(1);
                reveal_info->mut_src().front() = 0;
                reveal_info->mut_extra().resize(1);
                reveal_info->mut_extra().front() = 0;
                return {0, false};
            }
            cend = &node->immut_diffs()[size - 1];

            auto cmp = [node](const uint32_t & a, const uint32_t & b) noexcept {
                return a < b || (a == b && (node->immut_masks()[&a - node->immut_diffs().cbegin()] & ~(1 << 7)) >
                                           (node->immut_masks()[&b - node->immut_diffs().cbegin()] & ~(1 << 7)));
            };

            while (true) {
                const uint32_t * min_it = std::min_element(cbegin, cend, cmp);
                uint32_t diff_at = *min_it;
                uint8_t trans_mask = transMask(node->immut_masks()[min_it - node->immut_diffs().cbegin()]);

                uint8_t crit_byte = target.size() > diff_at ? charToUint8(target[diff_at])
                                                            : static_cast<uint8_t>(RIGHT_FIRST ? UINT8_MAX : 0);
                auto direct = static_cast<bool>((1 + (crit_byte | trans_mask)) >> 8);
                reveal_info->reveal(diff_at, uint8ToChar(trans_mask), direct);

                if (!direct) { // left
                    cend = min_it;
                } else { // right
                    cbegin = min_it + 1;
                }

                if (cbegin == cend) {
                    return {min_it - node->immut_diffs().cbegin(), direct};
                }
            }
        };

        template<bool RIGHT_FIRST>
        void loadToTarget(const Slice & target) {
            _usr.clear();
            RWLockReadGuard read_guard(&_index->_expand_lock);

            RWLockReadGuard node_read_guard(_index->offToNodeLock(_root));
            const BDNode * cursor = _index->offToMemNode(_root);
            while (true) {
                auto pos = findBestMatch<RIGHT_FIRST>(cursor, target, &_usr);
                size_t idx;
                bool direct;
                std::tie(idx, direct) = pos;

                _cursor = static_cast<int>(idx + direct);
                CritPtr ptr = cursor->immut_ptrs()[_cursor];
                if (ptr.isNull()) {
                    _valid = false;
                    return;
                }
                if (ptr.isNode()) {
                    node_read_guard = RWLockReadGuard(_index->offToNodeLock(ptr.asNode()));
                    cursor = _index->offToMemNode(ptr.asNode());
                } else {
                    _node_clone = *cursor;
                    _valid = true;
                    return;
                }
            }
        }

        Slice smallerKey() const noexcept {
            Slice s = key();
            Slice res;

            size_t i = s.size();
            do {
                --i;
                if ((_usr.immut_extra()[i] & _usr.immut_src()[i]) == 0) {
                    assert(i != 0);
                    continue;
                }

                auto * arr = reinterpret_cast<char *>(malloc(i + 1));
                res = Slice::pinnableSlice(arr, i + 1);
                memcpy(arr, s.data(), res.size());

                --arr[i];
                // coverity[leaked_storage]
                break;
            } while (true);

            assert(res.owned());
            return res;
        }

        Slice largerKey() const noexcept {
            Slice s = key();
            Slice res;

            size_t i = s.size();
            do {
                --i;
                char xor_res;
                if ((xor_res = (_usr.immut_extra()[i] ^ _usr.immut_src()[i])) == 0) {
                    assert(i != 0);
                    continue;
                }

                auto * arr = reinterpret_cast<char *>(malloc(i + 1));
                res = Slice::pinnableSlice(arr, i + 1);
                memcpy(arr, s.data(), res.size());

                auto n = __builtin_ffs(xor_res);
                arr[i] |= 1 << (n - 1); // 0 to 1
                arr[i] &= uint8ToChar(UINT8_MAX >> (n - 1) << (n - 1));
                // coverity[leaked_storage]
                break;
            } while (true);

            assert(res.owned());
            return res;
        }

        bool metMin() const noexcept {
            return std::all_of(_usr.immut_src().cbegin(), _usr.immut_src().cend(), [](char a) noexcept {
                return a == 0;
            });
        }

        bool metMax() const noexcept {
            return std::all_of(_usr.immut_src().cbegin(), _usr.immut_src().cend(), [this](const char & a) noexcept {
                return (a ^ _usr.immut_extra()[&a - &_usr.immut_src().front()]) == 0;
            });
        }
    };

    std::unique_ptr<Iterator<Slice/* usr */, OffsetToData>>
    BitDegradeTree::scan() const noexcept {
        return std::make_unique<BitDegradeTreeIterator>(this);
    }
}<|endoftext|>


<commit_before>#include "openmc/initialize.h"

#include <cstddef>
#include <cstdlib> // for getenv
#include <cstring>
#include <memory>
#include <string>
#include <vector>

#ifdef _OPENMP
#include <omp.h>
#endif
#include <fmt/core.h>

#include "openmc/capi.h"
#include "openmc/constants.h"
#include "openmc/cross_sections.h"
#include "openmc/error.h"
#include "openmc/geometry_aux.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/output.h"
#include "openmc/plot.h"
#include "openmc/random_lcg.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/string_utils.h"
#include "openmc/summary.h"
#include "openmc/tallies/tally.h"
#include "openmc/thermal.h"
#include "openmc/timer.h"

#ifdef LIBMESH
#include "libmesh/libmesh.h"
#endif

int openmc_init(int argc, char* argv[], const void* intracomm)
{
  using namespace openmc;

#ifdef OPENMC_MPI
  // Check if intracomm was passed
  MPI_Comm comm;
  if (intracomm) {
    comm = *static_cast<const MPI_Comm *>(intracomm);
  } else {
    comm = MPI_COMM_WORLD;
  }

  // Initialize MPI for C++
  initialize_mpi(comm);
#endif

  // Parse command-line arguments
  int err = parse_command_line(argc, argv);
  if (err) return err;

#ifdef LIBMESH

#ifdef _OPENMP
  int n_threads = omp_get_max_threads();
#else
  int n_threads = 1;
#endif

// initialize libMesh if it hasn't been initialized already
// by a call external to OpenMC
if (!settings::LMI && !libMesh::initialized())
{
#ifdef OPENMC_MPI
  // pass command line args, empty MPI communicator, and number of threads.
  // Because libMesh was not initialized, we assume that OpenMC is the primary
  // application and that its main MPI comm should be used.
  settings::LMI = std::make_unique<libMesh::LibMeshInit>(argc, argv, comm, n_threads);
#else
  // pass command line args, empty MPI communicator, and number of threads
  settings::LMI = std::make_unique<libMesh::LibMeshInit>(argc, argv, 0, n_threads);
#endif
}
#endif

  // Start total and initialization timer
  simulation::time_total.start();
  simulation::time_initialize.start();

#ifdef _OPENMP
  // If OMP_SCHEDULE is not set, default to a static schedule
  char* envvar = std::getenv("OMP_SCHEDULE");
  if (!envvar) {
    omp_set_schedule(omp_sched_static, 0);
  }
#endif

  // Initialize random number generator -- if the user specifies a seed, it
  // will be re-initialized later
  openmc::openmc_set_seed(DEFAULT_SEED);

  // Read XML input files
  read_input_xml();

  // Check for particle restart run
  if (settings::particle_restart_run) settings::run_mode = RunMode::PARTICLE;

  // Stop initialization timer
  simulation::time_initialize.stop();
  simulation::time_total.stop();

  return 0;
}

namespace openmc {

#ifdef OPENMC_MPI
void initialize_mpi(MPI_Comm intracomm)
{
  mpi::intracomm = intracomm;

  // Initialize MPI
  int flag;
  MPI_Initialized(&flag);
  if (!flag) MPI_Init(nullptr, nullptr);

  // Determine number of processes and rank for each
  MPI_Comm_size(intracomm, &mpi::n_procs);
  MPI_Comm_rank(intracomm, &mpi::rank);
  mpi::master = (mpi::rank == 0);

  // Create bank datatype
  Particle::Bank b;
  MPI_Aint disp[9];
  MPI_Get_address(&b.r, &disp[0]);
  MPI_Get_address(&b.u, &disp[1]);
  MPI_Get_address(&b.E, &disp[2]);
  MPI_Get_address(&b.wgt, &disp[3]);
  MPI_Get_address(&b.delayed_group, &disp[4]);
  MPI_Get_address(&b.surf_id, &disp[5]);
  MPI_Get_address(&b.particle, &disp[6]);
  MPI_Get_address(&b.parent_id, &disp[7]);
  MPI_Get_address(&b.progeny_id, &disp[8]);
  for (int i = 8; i >= 0; --i) {
    disp[i] -= disp[0];
  }

  int blocks[] {3, 3, 1, 1, 1, 1, 1, 1, 1};
  MPI_Datatype types[] {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_INT, MPI_LONG, MPI_LONG};
  MPI_Type_create_struct(9, blocks, disp, types, &mpi::bank);
  MPI_Type_commit(&mpi::bank);
}
#endif // OPENMC_MPI

int
parse_command_line(int argc, char* argv[])
{
  int last_flag = 0;
  for (int i=1; i < argc; ++i) {
    std::string arg {argv[i]};
    if (arg[0] == '-') {
      if (arg == "-p" || arg == "--plot") {
        settings::run_mode = RunMode::PLOTTING;
        settings::check_overlaps = true;

      } else if (arg == "-n" || arg == "--particles") {
        i += 1;
        settings::n_particles = std::stoll(argv[i]);

      } else if (arg == "-e" || arg == "--event") {
        settings::event_based = true;

      } else if (arg == "-r" || arg == "--restart") {
        i += 1;

        // Check what type of file this is
        hid_t file_id = file_open(argv[i], 'r', true);
        std::string filetype;
        read_attribute(file_id, "filetype", filetype);
        file_close(file_id);

        // Set path and flag for type of run
        if (filetype == "statepoint") {
          settings::path_statepoint = argv[i];
          settings::restart_run = true;
        } else if (filetype == "particle restart") {
          settings::path_particle_restart = argv[i];
          settings::particle_restart_run = true;
        } else {
          auto msg = fmt::format("Unrecognized file after restart flag: {}.", filetype);
          strcpy(openmc_err_msg, msg.c_str());
          return OPENMC_E_INVALID_ARGUMENT;
        }

        // If its a restart run check for additional source file
        if (settings::restart_run && i + 1 < argc) {
          // Check if it has extension we can read
          if (ends_with(argv[i+1], ".h5")) {

            // Check file type is a source file
            file_id = file_open(argv[i+1], 'r', true);
            read_attribute(file_id, "filetype", filetype);
            file_close(file_id);
            if (filetype != "source") {
              std::string msg {"Second file after restart flag must be a source file"};
              strcpy(openmc_err_msg, msg.c_str());
              return OPENMC_E_INVALID_ARGUMENT;
            }

            // It is a source file
            settings::path_sourcepoint = argv[i+1];
            i += 1;

          } else {
            // Source is in statepoint file
            settings::path_sourcepoint = settings::path_statepoint;
          }

        } else {
          // Source is assumed to be in statepoint file
          settings::path_sourcepoint = settings::path_statepoint;
        }

      } else if (arg == "-g" || arg == "--geometry-debug") {
      settings::check_overlaps = true;
      } else if (arg == "-c" || arg == "--volume") {
        settings::run_mode = RunMode::VOLUME;
      } else if (arg == "-s" || arg == "--threads") {
        // Read number of threads
        i += 1;

#ifdef _OPENMP
        // Read and set number of OpenMP threads
        int n_threads = std::stoi(argv[i]);
        if (n_threads < 1) {
          std::string msg {"Number of threads must be positive."};
          strcpy(openmc_err_msg, msg.c_str());
          return OPENMC_E_INVALID_ARGUMENT;
        }
        omp_set_num_threads(n_threads);
#else
        if (mpi::master) {
          warning("Ignoring number of threads specified on command line.");
        }
#endif

      } else if (arg == "-?" || arg == "-h" || arg == "--help") {
        print_usage();
        return OPENMC_E_UNASSIGNED;

      } else if (arg == "-v" || arg == "--version") {
        print_version();
        return OPENMC_E_UNASSIGNED;

      } else if (arg == "-t" || arg == "--track") {
        settings::write_all_tracks = true;

      } else {
        fmt::print(stderr, "Unknown option: {}\n", argv[i]);
        print_usage();
        return OPENMC_E_UNASSIGNED;
      }

      last_flag = i;
    }
  }

  // Determine directory where XML input files are
  if (argc > 1 && last_flag < argc - 1) {
    settings::path_input = std::string(argv[last_flag + 1]);

    // Add slash at end of directory if it isn't there
    if (!ends_with(settings::path_input, "/")) {
      settings::path_input += "/";
    }
  }

  return 0;
}

void read_input_xml()
{
  read_settings_xml();
  read_cross_sections_xml();
  read_materials_xml();
  read_geometry_xml();

  // Final geometry setup and assign temperatures
  finalize_geometry();

  // Finalize cross sections having assigned temperatures
  finalize_cross_sections();

  read_tallies_xml();

  // Initialize distribcell_filters
  prepare_distribcell();

  if (settings::run_mode == RunMode::PLOTTING) {
    // Read plots.xml if it exists
    read_plots_xml();
    if (mpi::master && settings::verbosity >= 5) print_plot();

  } else {
    // Write summary information
    if (mpi::master && settings::output_summary) write_summary();

    // Warn if overlap checking is on
    if (mpi::master && settings::check_overlaps) {
      warning("Cell overlap checking is ON.");
    }
  }

}

} // namespace openmc
<commit_msg>Adding check that the LibMeshInit object is set.<commit_after>#include "openmc/initialize.h"

#include <cstddef>
#include <cstdlib> // for getenv
#include <cstring>
#include <memory>
#include <string>
#include <vector>

#ifdef _OPENMP
#include <omp.h>
#endif
#include <fmt/core.h>

#include "openmc/capi.h"
#include "openmc/constants.h"
#include "openmc/cross_sections.h"
#include "openmc/error.h"
#include "openmc/geometry_aux.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/output.h"
#include "openmc/plot.h"
#include "openmc/random_lcg.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/string_utils.h"
#include "openmc/summary.h"
#include "openmc/tallies/tally.h"
#include "openmc/thermal.h"
#include "openmc/timer.h"

#ifdef LIBMESH
#include "libmesh/libmesh.h"
#endif

int openmc_init(int argc, char* argv[], const void* intracomm)
{
  using namespace openmc;

#ifdef OPENMC_MPI
  // Check if intracomm was passed
  MPI_Comm comm;
  if (intracomm) {
    comm = *static_cast<const MPI_Comm *>(intracomm);
  } else {
    comm = MPI_COMM_WORLD;
  }

  // Initialize MPI for C++
  initialize_mpi(comm);
#endif

  // Parse command-line arguments
  int err = parse_command_line(argc, argv);
  if (err) return err;

#ifdef LIBMESH

#ifdef _OPENMP
  int n_threads = omp_get_max_threads();
#else
  int n_threads = 1;
#endif

// initialize libMesh if it hasn't been initialized already
// (if initialized externally, the LMI object needs to be provided also)
if (!settings::LMI && !libMesh::initialized())
{
#ifdef OPENMC_MPI
  // pass command line args, empty MPI communicator, and number of threads.
  // Because libMesh was not initialized, we assume that OpenMC is the primary
  // application and that its main MPI comm should be used.
  settings::LMI = std::make_unique<libMesh::LibMeshInit>(argc, argv, comm, n_threads);
#else
  // pass command line args, empty MPI communicator, and number of threads
  settings::LMI = std::make_unique<libMesh::LibMeshInit>(argc, argv, 0, n_threads);
#endif
}

if (!settings::LMI) {
  fatal_error("libMesh::LibMeshInit object isn't set.");
}
#endif

  // Start total and initialization timer
  simulation::time_total.start();
  simulation::time_initialize.start();

#ifdef _OPENMP
  // If OMP_SCHEDULE is not set, default to a static schedule
  char* envvar = std::getenv("OMP_SCHEDULE");
  if (!envvar) {
    omp_set_schedule(omp_sched_static, 0);
  }
#endif

  // Initialize random number generator -- if the user specifies a seed, it
  // will be re-initialized later
  openmc::openmc_set_seed(DEFAULT_SEED);

  // Read XML input files
  read_input_xml();

  // Check for particle restart run
  if (settings::particle_restart_run) settings::run_mode = RunMode::PARTICLE;

  // Stop initialization timer
  simulation::time_initialize.stop();
  simulation::time_total.stop();

  return 0;
}

namespace openmc {

#ifdef OPENMC_MPI
void initialize_mpi(MPI_Comm intracomm)
{
  mpi::intracomm = intracomm;

  // Initialize MPI
  int flag;
  MPI_Initialized(&flag);
  if (!flag) MPI_Init(nullptr, nullptr);

  // Determine number of processes and rank for each
  MPI_Comm_size(intracomm, &mpi::n_procs);
  MPI_Comm_rank(intracomm, &mpi::rank);
  mpi::master = (mpi::rank == 0);

  // Create bank datatype
  Particle::Bank b;
  MPI_Aint disp[9];
  MPI_Get_address(&b.r, &disp[0]);
  MPI_Get_address(&b.u, &disp[1]);
  MPI_Get_address(&b.E, &disp[2]);
  MPI_Get_address(&b.wgt, &disp[3]);
  MPI_Get_address(&b.delayed_group, &disp[4]);
  MPI_Get_address(&b.surf_id, &disp[5]);
  MPI_Get_address(&b.particle, &disp[6]);
  MPI_Get_address(&b.parent_id, &disp[7]);
  MPI_Get_address(&b.progeny_id, &disp[8]);
  for (int i = 8; i >= 0; --i) {
    disp[i] -= disp[0];
  }

  int blocks[] {3, 3, 1, 1, 1, 1, 1, 1, 1};
  MPI_Datatype types[] {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_INT, MPI_LONG, MPI_LONG};
  MPI_Type_create_struct(9, blocks, disp, types, &mpi::bank);
  MPI_Type_commit(&mpi::bank);
}
#endif // OPENMC_MPI

int
parse_command_line(int argc, char* argv[])
{
  int last_flag = 0;
  for (int i=1; i < argc; ++i) {
    std::string arg {argv[i]};
    if (arg[0] == '-') {
      if (arg == "-p" || arg == "--plot") {
        settings::run_mode = RunMode::PLOTTING;
        settings::check_overlaps = true;

      } else if (arg == "-n" || arg == "--particles") {
        i += 1;
        settings::n_particles = std::stoll(argv[i]);

      } else if (arg == "-e" || arg == "--event") {
        settings::event_based = true;

      } else if (arg == "-r" || arg == "--restart") {
        i += 1;

        // Check what type of file this is
        hid_t file_id = file_open(argv[i], 'r', true);
        std::string filetype;
        read_attribute(file_id, "filetype", filetype);
        file_close(file_id);

        // Set path and flag for type of run
        if (filetype == "statepoint") {
          settings::path_statepoint = argv[i];
          settings::restart_run = true;
        } else if (filetype == "particle restart") {
          settings::path_particle_restart = argv[i];
          settings::particle_restart_run = true;
        } else {
          auto msg = fmt::format("Unrecognized file after restart flag: {}.", filetype);
          strcpy(openmc_err_msg, msg.c_str());
          return OPENMC_E_INVALID_ARGUMENT;
        }

        // If its a restart run check for additional source file
        if (settings::restart_run && i + 1 < argc) {
          // Check if it has extension we can read
          if (ends_with(argv[i+1], ".h5")) {

            // Check file type is a source file
            file_id = file_open(argv[i+1], 'r', true);
            read_attribute(file_id, "filetype", filetype);
            file_close(file_id);
            if (filetype != "source") {
              std::string msg {"Second file after restart flag must be a source file"};
              strcpy(openmc_err_msg, msg.c_str());
              return OPENMC_E_INVALID_ARGUMENT;
            }

            // It is a source file
            settings::path_sourcepoint = argv[i+1];
            i += 1;

          } else {
            // Source is in statepoint file
            settings::path_sourcepoint = settings::path_statepoint;
          }

        } else {
          // Source is assumed to be in statepoint file
          settings::path_sourcepoint = settings::path_statepoint;
        }

      } else if (arg == "-g" || arg == "--geometry-debug") {
      settings::check_overlaps = true;
      } else if (arg == "-c" || arg == "--volume") {
        settings::run_mode = RunMode::VOLUME;
      } else if (arg == "-s" || arg == "--threads") {
        // Read number of threads
        i += 1;

#ifdef _OPENMP
        // Read and set number of OpenMP threads
        int n_threads = std::stoi(argv[i]);
        if (n_threads < 1) {
          std::string msg {"Number of threads must be positive."};
          strcpy(openmc_err_msg, msg.c_str());
          return OPENMC_E_INVALID_ARGUMENT;
        }
        omp_set_num_threads(n_threads);
#else
        if (mpi::master) {
          warning("Ignoring number of threads specified on command line.");
        }
#endif

      } else if (arg == "-?" || arg == "-h" || arg == "--help") {
        print_usage();
        return OPENMC_E_UNASSIGNED;

      } else if (arg == "-v" || arg == "--version") {
        print_version();
        return OPENMC_E_UNASSIGNED;

      } else if (arg == "-t" || arg == "--track") {
        settings::write_all_tracks = true;

      } else {
        fmt::print(stderr, "Unknown option: {}\n", argv[i]);
        print_usage();
        return OPENMC_E_UNASSIGNED;
      }

      last_flag = i;
    }
  }

  // Determine directory where XML input files are
  if (argc > 1 && last_flag < argc - 1) {
    settings::path_input = std::string(argv[last_flag + 1]);

    // Add slash at end of directory if it isn't there
    if (!ends_with(settings::path_input, "/")) {
      settings::path_input += "/";
    }
  }

  return 0;
}

void read_input_xml()
{
  read_settings_xml();
  read_cross_sections_xml();
  read_materials_xml();
  read_geometry_xml();

  // Final geometry setup and assign temperatures
  finalize_geometry();

  // Finalize cross sections having assigned temperatures
  finalize_cross_sections();

  read_tallies_xml();

  // Initialize distribcell_filters
  prepare_distribcell();

  if (settings::run_mode == RunMode::PLOTTING) {
    // Read plots.xml if it exists
    read_plots_xml();
    if (mpi::master && settings::verbosity >= 5) print_plot();

  } else {
    // Write summary information
    if (mpi::master && settings::output_summary) write_summary();

    // Warn if overlap checking is on
    if (mpi::master && settings::check_overlaps) {
      warning("Cell overlap checking is ON.");
    }
  }

}

} // namespace openmc
<|endoftext|>


<commit_before>//
//  inpalprime.cpp
//  InPal
//
//  Created by Bryan Triana on 6/21/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#include "inpalprime.hpp"
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>

std::size_t inpal::prime::max_prime(std::size_t num)
{
    auto primes = prime_sieve(num);
    auto it = std::find(primes.rbegin(), primes.rend(), true);

    return primes.size()-std::distance(primes.rbegin(), it)-1;
}

std::size_t inpal::prime::prime_count(std::size_t num)
{
    auto primes = prime_sieve(num);

    return std::count(primes.begin(), primes.end(), true);
}

double inpal::prime::prime_density(double range)
{
    return prime_count(range)/range;
}

bool inpal::prime::prime_test(std::size_t num)
{
    return num == max_prime(num);
}

bool inpal::prime::twin_test(std::size_t num)
{
    auto primes = prime_sieve(num+2);

    return num!=2 && primes[primes.size()-3] && (primes[primes.size()-1] || primes[primes.size()-5]);
}

bool inpal::prime::cousin_test(std::size_t num)
{
    auto primes = prime_sieve(num+4);

    return  num!=2 && primes[primes.size()-5] && (primes[primes.size()-1] || primes[primes.size()-9]);
}

bool inpal::prime::sexy_test(std::size_t num)
{
    auto primes = prime_sieve(num+6);

    return (num!=2 && num!=3) && primes[primes.size()-7] && (primes[primes.size()-1] || primes[primes.size()-13]);
}

std::size_t inpal::prime::max_palprime(std::size_t num)
{
    auto primes = prime_sieve(num);

    for(std::size_t i=num; i>=2; --i) if(primes[i] && pal_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::max_factor(std::size_t num)
{
    return factorizer(num).back();
}

std::size_t inpal::prime::count_factors(std::size_t num)
{
    return factorizer(num).size();
}

std::vector<bool> inpal::prime::prime_sieve(std::size_t range)
{
    std::vector<bool> p_test(range+1, false);

    //defines square root of range
    std::size_t root = ceil(sqrt(range));

    //sieve axioms
    for(std::size_t x=1; x<=root; x++)
        for(std::size_t y=1; y<=root; y++)
        {
            std::size_t i = (4*x*x)+(y*y);
            if (i<=range && (i%12==1 || i%12==5))
            {
                p_test[i].flip();
            }

            i = (3*x*x)+(y*y);
            if(i<=range && i%12==7)
            {
                p_test[i].flip();
            }

            i = (3*x*x)-(y*y);
            if(x>y && i<=range && i%12==11)
            {
                p_test[i].flip();
            }
        }

    //marks 2,3,5 and 7 as prime numbers
    p_test[2]=p_test[3]=p_test[5]=p_test[7]=true;

    //marks all multiples of primes as non primes
    for(std::size_t r=5; r<=root; r++)
    {
        if((p_test[r]))
        {
            for(std::size_t j=r*r; j<=range; j+=r*r)
            {
                p_test[j]=false;
            }
        }
    }

    return p_test;
}

std::vector<std::size_t> inpal::prime::factorizer(std::size_t num)
{
    std::vector<std::size_t> p_fac;
    std::size_t p = 2;

    //trial division
    while(p<=num)
    {
        while(num%p==0)
        {
            p_fac.push_back(num);
            num=num/p;
        }
        p += p==2 ? 1 : 2;
    }

    return p_fac;
}

bool inpal::prime::pal_test(std::size_t num)
{
    //converts num to a string
    std::string rev = std::to_string(num);

    //checks if the reverse of rev is equal to rev
    if(std::equal(rev.begin(), rev.begin()+rev.size()/2, rev.rbegin()))
    {
        return true;
    }

    return false;
}
<commit_msg>Delete inpalprime.cpp<commit_after><|endoftext|>


<commit_before>/**
 * This file tests whether the HyPerCol parses
 * the -rows and -columns arguments correctly
 * Use with mpirun -np 6
 *
 */

#ifndef PV_USE_MPI
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
   fprintf(stderr, "%s: this test can only be used under MPI with exactly six processes.\n", argv[0]);
   // TODO Greater than six should be permissible, with the excess over 6 being idle
   exit(EXIT_FAILURE);
}
#else // ifndef PV_USE_MPI

#include "../src/include/pv_common.h"
#include "../src/columns/HyPerCol.hpp"
#include "../src/layers/ANNLayer.hpp"
#include "../src/io/io.h"
#include <assert.h>
#ifdef PV_USE_MPI
#include <mpi.h>

int buildandverify(int argc, char * argv[]);
int verifyLoc(PV::HyPerCol * loc, int rows, int columns);
int dumpLoc(const PVLayerLoc * loc, int rank);
#endif // PV_USE_MPI

using namespace PV;

int main(int argc, char * argv[]) {
   int status = PV_SUCCESS;
   int mpi_initialized_on_entry;
   MPI_Initialized(&mpi_initialized_on_entry);
   if( !mpi_initialized_on_entry ) MPI_Init(&argc, &argv);
   int numProcs;
   MPI_Comm_size(MPI_COMM_WORLD, &numProcs);

   if( numProcs != 6) {
      fprintf(stderr, "%s: this test can only be used under MPI with exactly six processes.\n", argv[0]);
      // TODO Greater than six should be permissible, with the excess over 6 being idle
      exit(EXIT_FAILURE);
   }

#undef REQUIRE_RETURN // #define if the program should wait for carriage return before proceeding
#ifdef REQUIRE_RETURN
   int charhit;
   fflush(stdout);
   int rank;
   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
   if( rank == 0 ) {
      printf("Hit enter to begin! ");
      fflush(stdout);
      charhit = getc(stdin);
   }
   int ierr;
   ierr = MPI_Bcast(&charhit, 1, MPI_INT, 0, MPI_COMM_WORLD);
#endif // REQUIRE_RETURN

#define TEST_MPI_SPECIFYROWCOLUMNS_ARGC 7
   char * cl_args[TEST_MPI_SPECIFYROWCOLUMNS_ARGC];
   cl_args[0] = argv[0];
   cl_args[1] = strdup("-p");
   cl_args[2] = strdup("input/test_mpi_specifyrowscolumns.params");
   cl_args[3] = strdup("-rows");
   cl_args[4] = strdup("2");
   cl_args[5] = strdup("-columns");
   cl_args[6] = strdup("3");
   buildandverify(TEST_MPI_SPECIFYROWCOLUMNS_ARGC, cl_args);

   free(cl_args[4]);
   cl_args[4] = strdup("3");
   free(cl_args[6]);
   cl_args[6] = strdup("2");
   buildandverify(TEST_MPI_SPECIFYROWCOLUMNS_ARGC, cl_args);

   for( int arg=1; arg<TEST_MPI_SPECIFYROWCOLUMNS_ARGC; arg++ ) {
      free(cl_args[arg]);
   }
   if( !mpi_initialized_on_entry ) MPI_Finalize();
   return status;
}

int buildandverify(int argc, char * argv[]) {
   for( int i=0; i<argc; i++ ) {
      assert(argv[i] != NULL);
   }
   PV::HyPerCol * hc = new PV::HyPerCol("column", argc, argv);
   /* PV::ANNLayer * layer = */ new PV::ANNLayer("layer", hc);
   int rows = -1;
   int columns = -1;
   pv_getopt_int(argc, argv, "-rows", &rows);
   pv_getopt_int(argc, argv, "-columns", &columns);
   assert(rows >= 0 && columns >= 0);
   int status = verifyLoc(hc, rows, columns);
   delete hc;
   return status;
}

int verifyLoc(PV::HyPerCol * hc, int rows, int columns) {
   int status = PV_SUCCESS;
   int testpassed;
   const PVLayerLoc * loc = hc->getLayer(0)->getLayerLoc();
   int rank = hc->icCommunicator()->commRank();
   assert(rows == hc->icCommunicator()->numCommRows());
   assert(columns == hc->icCommunicator()->numCommColumns());
   PVParams * params = hc->parameters();
   int nxGlobFromParams = params->value("column", "nx");
   int nyGlobFromParams = params->value("column", "ny");
   testpassed = (loc->nx == nxGlobFromParams/columns) &&
                (loc->ny == nyGlobFromParams/rows) &&
                (loc->nf == params->value("layer", "nf")) &&
                (loc->nb == params->value("layer", "marginWidth")) &&
                (loc->nxGlobal == nxGlobFromParams) &&
                (loc->nyGlobal == nyGlobFromParams) &&
                (loc->kx0 == loc->nx * (rank % columns)) &&
                (loc->ky0 == loc->ny * (rank / columns));

   PVLayerLoc mpiLoc;
   if( rank == 0 ) {
      printf("Testing with %d rows by %d columns of subprocesses.\n", rows, columns);
      if( testpassed ) {
         printf("Rank 0 passed.\n");
      }
      else {
         dumpLoc(loc, 0);
         fflush(stdout);
         fprintf(stderr, "Rank 0 FAILED\n");
         status = PV_FAILURE;
      }
      // Receive each process's testpassed value and output it.
      for( int src=1; src<hc->icCommunicator()->commSize(); src++) {
         int remotepassed;
         MPI_Recv(&remotepassed, 1, MPI_INT, src, 10, hc->icCommunicator()->communicator(), MPI_STATUS_IGNORE);
         if( remotepassed ) {
            fprintf(stderr, "Rank %d passed.\n", src);
         }
         else {
            MPI_Recv(&mpiLoc, sizeof(PVLayerLoc), MPI_CHAR, src, 20, hc->icCommunicator()->communicator(), MPI_STATUS_IGNORE);
            dumpLoc(&mpiLoc, src);
            fflush(stdout);
            fprintf(stderr, "Rank %d FAILED\n", src);
            status = PV_FAILURE;
         }
      }
   }
   else {
      // Send each process's testpassed value to root process.
      MPI_Send(&testpassed, 1, MPI_INT, 0, 10, hc->icCommunicator()->communicator());
      if( !testpassed ) {
         memcpy(&mpiLoc, loc, sizeof(PVLayerLoc));
         MPI_Send(&mpiLoc, sizeof(PVLayerLoc), MPI_CHAR, 0, 20, hc->icCommunicator()->communicator());
      }
   }
   assert(status == PV_SUCCESS);
   return status;
}

int dumpLoc(const PVLayerLoc * loc, int rank) {
   if( loc == NULL ) return PV_FAILURE;
   printf("Rank %d: nx=%d, ny=%d, nf=%d, nxGlobal=%d, nyGlobal=%d, kx0=%d, ky0=%d\n",
          rank, loc->nx, loc->ny, loc->nf, loc->nxGlobal, loc->nyGlobal, loc->kx0, loc->ky0);
   return PV_SUCCESS;
}
#endif // PV_USE_MPI
<commit_msg>Need to load pv_common.h before checking if PV_USE_MPI is defined<commit_after>/**
 * This file tests whether the HyPerCol parses
 * the -rows and -columns arguments correctly
 * Use with mpirun -np 6
 *
 */

#include "../src/include/pv_common.h"

#ifndef PV_USE_MPI
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
   fprintf(stderr, "%s: this test can only be used under MPI with exactly six processes.\n", argv[0]);
   // TODO Greater than six should be permissible, with the excess over 6 being idle
   exit(EXIT_FAILURE);
}
#else // ifndef PV_USE_MPI

#include "../src/columns/HyPerCol.hpp"
#include "../src/layers/ANNLayer.hpp"
#include "../src/io/io.h"
#include <assert.h>
#ifdef PV_USE_MPI
#include <mpi.h>

int buildandverify(int argc, char * argv[]);
int verifyLoc(PV::HyPerCol * loc, int rows, int columns);
int dumpLoc(const PVLayerLoc * loc, int rank);
#endif // PV_USE_MPI

using namespace PV;

int main(int argc, char * argv[]) {
   int status = PV_SUCCESS;
   int mpi_initialized_on_entry;
   MPI_Initialized(&mpi_initialized_on_entry);
   if( !mpi_initialized_on_entry ) MPI_Init(&argc, &argv);
   int numProcs;
   MPI_Comm_size(MPI_COMM_WORLD, &numProcs);

   if( numProcs != 6) {
      fprintf(stderr, "%s: this test can only be used under MPI with exactly six processes.\n", argv[0]);
      // TODO Greater than six should be permissible, with the excess over 6 being idle
      exit(EXIT_FAILURE);
   }

#undef REQUIRE_RETURN // #define if the program should wait for carriage return before proceeding
#ifdef REQUIRE_RETURN
   int charhit;
   fflush(stdout);
   int rank;
   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
   if( rank == 0 ) {
      printf("Hit enter to begin! ");
      fflush(stdout);
      charhit = getc(stdin);
   }
   int ierr;
   ierr = MPI_Bcast(&charhit, 1, MPI_INT, 0, MPI_COMM_WORLD);
#endif // REQUIRE_RETURN

#define TEST_MPI_SPECIFYROWCOLUMNS_ARGC 7
   char * cl_args[TEST_MPI_SPECIFYROWCOLUMNS_ARGC];
   cl_args[0] = argv[0];
   cl_args[1] = strdup("-p");
   cl_args[2] = strdup("input/test_mpi_specifyrowscolumns.params");
   cl_args[3] = strdup("-rows");
   cl_args[4] = strdup("2");
   cl_args[5] = strdup("-columns");
   cl_args[6] = strdup("3");
   buildandverify(TEST_MPI_SPECIFYROWCOLUMNS_ARGC, cl_args);

   free(cl_args[4]);
   cl_args[4] = strdup("3");
   free(cl_args[6]);
   cl_args[6] = strdup("2");
   buildandverify(TEST_MPI_SPECIFYROWCOLUMNS_ARGC, cl_args);

   for( int arg=1; arg<TEST_MPI_SPECIFYROWCOLUMNS_ARGC; arg++ ) {
      free(cl_args[arg]);
   }
   if( !mpi_initialized_on_entry ) MPI_Finalize();
   return status;
}

int buildandverify(int argc, char * argv[]) {
   for( int i=0; i<argc; i++ ) {
      assert(argv[i] != NULL);
   }
   PV::HyPerCol * hc = new PV::HyPerCol("column", argc, argv);
   /* PV::ANNLayer * layer = */ new PV::ANNLayer("layer", hc);
   int rows = -1;
   int columns = -1;
   pv_getopt_int(argc, argv, "-rows", &rows);
   pv_getopt_int(argc, argv, "-columns", &columns);
   assert(rows >= 0 && columns >= 0);
   int status = verifyLoc(hc, rows, columns);
   delete hc;
   return status;
}

int verifyLoc(PV::HyPerCol * hc, int rows, int columns) {
   int status = PV_SUCCESS;
   int testpassed;
   const PVLayerLoc * loc = hc->getLayer(0)->getLayerLoc();
   int rank = hc->icCommunicator()->commRank();
   assert(rows == hc->icCommunicator()->numCommRows());
   assert(columns == hc->icCommunicator()->numCommColumns());
   PVParams * params = hc->parameters();
   int nxGlobFromParams = params->value("column", "nx");
   int nyGlobFromParams = params->value("column", "ny");
   testpassed = (loc->nx == nxGlobFromParams/columns) &&
                (loc->ny == nyGlobFromParams/rows) &&
                (loc->nf == params->value("layer", "nf")) &&
                (loc->nb == params->value("layer", "marginWidth")) &&
                (loc->nxGlobal == nxGlobFromParams) &&
                (loc->nyGlobal == nyGlobFromParams) &&
                (loc->kx0 == loc->nx * (rank % columns)) &&
                (loc->ky0 == loc->ny * (rank / columns));

   PVLayerLoc mpiLoc;
   if( rank == 0 ) {
      printf("Testing with %d rows by %d columns of subprocesses.\n", rows, columns);
      if( testpassed ) {
         printf("Rank 0 passed.\n");
      }
      else {
         dumpLoc(loc, 0);
         fflush(stdout);
         fprintf(stderr, "Rank 0 FAILED\n");
         status = PV_FAILURE;
      }
      // Receive each process's testpassed value and output it.
      for( int src=1; src<hc->icCommunicator()->commSize(); src++) {
         int remotepassed;
         MPI_Recv(&remotepassed, 1, MPI_INT, src, 10, hc->icCommunicator()->communicator(), MPI_STATUS_IGNORE);
         if( remotepassed ) {
            fprintf(stderr, "Rank %d passed.\n", src);
         }
         else {
            MPI_Recv(&mpiLoc, sizeof(PVLayerLoc), MPI_CHAR, src, 20, hc->icCommunicator()->communicator(), MPI_STATUS_IGNORE);
            dumpLoc(&mpiLoc, src);
            fflush(stdout);
            fprintf(stderr, "Rank %d FAILED\n", src);
            status = PV_FAILURE;
         }
      }
   }
   else {
      // Send each process's testpassed value to root process.
      MPI_Send(&testpassed, 1, MPI_INT, 0, 10, hc->icCommunicator()->communicator());
      if( !testpassed ) {
         memcpy(&mpiLoc, loc, sizeof(PVLayerLoc));
         MPI_Send(&mpiLoc, sizeof(PVLayerLoc), MPI_CHAR, 0, 20, hc->icCommunicator()->communicator());
      }
   }
   assert(status == PV_SUCCESS);
   return status;
}

int dumpLoc(const PVLayerLoc * loc, int rank) {
   if( loc == NULL ) return PV_FAILURE;
   printf("Rank %d: nx=%d, ny=%d, nf=%d, nxGlobal=%d, nyGlobal=%d, kx0=%d, ky0=%d\n",
          rank, loc->nx, loc->ny, loc->nf, loc->nxGlobal, loc->nyGlobal, loc->kx0, loc->ky0);
   return PV_SUCCESS;
}
#endif // PV_USE_MPI
<|endoftext|>


<commit_before>//===- GenerateCode.cpp - Functions for generating executable files  ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains functions for generating executable files once linking
// has finished.  This includes generating a shell script to run the JIT or
// a native executable derived from the bytecode.
//
//===----------------------------------------------------------------------===//

#include "gccld.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/Linker.h"
#include "Support/SystemUtils.h"
#include "Support/CommandLine.h"
using namespace llvm;

namespace {
  cl::opt<bool>
  DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify intermediate results of all passes"));

  cl::opt<bool>
  DisableOptimizations("disable-opt",
                       cl::desc("Do not run any optimization passes"));
  cl::opt<bool>
  DisableGlobalsModRef("disable-globalsmodref", cl::Hidden,
                      cl::desc("Turn on the more aggressive alias analysis"));
}

/// CopyEnv - This function takes an array of environment variables and makes a
/// copy of it.  This copy can then be manipulated any way the caller likes
/// without affecting the process's real environment.
///
/// Inputs:
///  envp - An array of C strings containing an environment.
///
/// Return value:
///  NULL - An error occurred.
///
///  Otherwise, a pointer to a new array of C strings is returned.  Every string
///  in the array is a duplicate of the one in the original array (i.e. we do
///  not copy the char *'s from one array to another).
///
static char ** CopyEnv(char ** const envp) {
  // Count the number of entries in the old list;
  unsigned entries;   // The number of entries in the old environment list
  for (entries = 0; envp[entries] != NULL; entries++)
    /*empty*/;

  // Add one more entry for the NULL pointer that ends the list.
  ++entries;

  // If there are no entries at all, just return NULL.
  if (entries == 0)
    return NULL;

  // Allocate a new environment list.
  char **newenv = new char* [entries];
  if ((newenv = new char* [entries]) == NULL)
    return NULL;

  // Make a copy of the list.  Don't forget the NULL that ends the list.
  entries = 0;
  while (envp[entries] != NULL) {
    newenv[entries] = new char[strlen (envp[entries]) + 1];
    strcpy (newenv[entries], envp[entries]);
    ++entries;
  }
  newenv[entries] = NULL;

  return newenv;
}

/// RemoveEnv - Remove the specified environment variable from the environment
/// array.
///
/// Inputs:
///  name - The name of the variable to remove.  It cannot be NULL.
///  envp - The array of environment variables.  It cannot be NULL.
///
/// Notes:
///  This is mainly done because functions to remove items from the environment
///  are not available across all platforms.  In particular, Solaris does not
///  seem to have an unsetenv() function or a setenv() function (or they are
///  undocumented if they do exist).
///
static void RemoveEnv(const char * name, char ** const envp) {
  for (unsigned index=0; envp[index] != NULL; index++) {
    // Find the first equals sign in the array and make it an EOS character.
    char *p = strchr (envp[index], '=');
    if (p == NULL)
      continue;
    else
      *p = '\0';

    // Compare the two strings.  If they are equal, zap this string.
    // Otherwise, restore it.
    if (!strcmp(name, envp[index]))
      *envp[index] = '\0';
    else
      *p = '=';
  }

  return;
}

static inline void addPass(PassManager &PM, Pass *P) {
  // Add the pass to the pass manager...
  PM.add(P);

  // If we are verifying all of the intermediate steps, add the verifier...
  if (Verify) PM.add(createVerifierPass());
}

/// GenerateBytecode - generates a bytecode file from the specified module.
///
/// Inputs:
///  M           - The module for which bytecode should be generated.
///  Strip       - Flags whether symbols should be stripped from the output.
///  Internalize - Flags whether all symbols should be marked internal.
///  Out         - Pointer to file stream to which to write the output.
///
/// Returns non-zero value on error.
///
int llvm::GenerateBytecode(Module *M, bool Strip, bool Internalize,
                           std::ostream *Out) {
  // In addition to just linking the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  PassManager Passes;

  if (Verify) Passes.add(createVerifierPass());

  // Add an appropriate TargetData instance for this module...
  addPass(Passes, new TargetData("gccld", M));

  // Often if the programmer does not specify proper prototypes for the
  // functions they are calling, they end up calling a vararg version of the
  // function that does not get a body filled in (the real function has typed
  // arguments).  This pass merges the two functions.
  addPass(Passes, createFunctionResolvingPass());

  if (!DisableOptimizations) {
    if (Internalize) {
      // Now that composite has been compiled, scan through the module, looking
      // for a main function.  If main is defined, mark all other functions
      // internal.
      addPass(Passes, createInternalizePass());
    }

    // Now that we internalized some globals, see if we can mark any globals as
    // being constant!
    addPass(Passes, createGlobalConstifierPass());

    // Linking modules together can lead to duplicated global constants, only
    // keep one copy of each constant...
    addPass(Passes, createConstantMergePass());

    // If the -s command line option was specified, strip the symbols out of the
    // resulting program to make it smaller.  -s is a GCC option that we are
    // supporting.
    if (Strip)
      addPass(Passes, createSymbolStrippingPass());

    // Propagate constants at call sites into the functions they call.
    addPass(Passes, createIPConstantPropagationPass());

    // Remove unused arguments from functions...
    addPass(Passes, createDeadArgEliminationPass());

    if (!DisableInline)
      addPass(Passes, createFunctionInliningPass()); // Inline small functions

    addPass(Passes, createPruneEHPass());            // Remove dead EH info
    addPass(Passes, createGlobalDCEPass());          // Remove dead functions

    // If we didn't decide to inline a function, check to see if we can
    // transform it to pass arguments by value instead of by reference.
    addPass(Passes, createArgumentPromotionPass());

    // The IPO passes may leave cruft around.  Clean up after them.
    addPass(Passes, createInstructionCombiningPass());

    addPass(Passes, createScalarReplAggregatesPass()); // Break up allocas

    // Run a few AA driven optimizations here and now, to cleanup the code.
    if (!DisableGlobalsModRef)
      addPass(Passes, createGlobalsModRefPass());    // IP alias analysis

    addPass(Passes, createLICMPass());               // Hoist loop invariants
    addPass(Passes, createLoadValueNumberingPass()); // GVN for load instrs
    addPass(Passes, createGCSEPass());               // Remove common subexprs
    addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores

    // Cleanup and simplify the code after the scalar optimizations.
    addPass(Passes, createInstructionCombiningPass());

    // Delete basic blocks, which optimization passes may have killed...
    addPass(Passes, createCFGSimplificationPass());

    // Now that we have optimized the program, discard unreachable functions...
    addPass(Passes, createGlobalDCEPass());
  }

  // Make sure everything is still good.
  Passes.add(createVerifierPass());

  // Add the pass that writes bytecode to the output file...
  addPass(Passes, new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M);

  return 0;
}

/// GenerateAssembly - generates a native assembly language source file from the
/// specified bytecode file.
///
/// Inputs:
///  InputFilename  - The name of the output bytecode file.
///  OutputFilename - The name of the file to generate.
///  llc            - The pathname to use for LLC.
///  envp           - The environment to use when running LLC.
///
/// Return non-zero value on error.
///
int llvm::GenerateAssembly(const std::string &OutputFilename,
                           const std::string &InputFilename,
                           const std::string &llc,
                           char ** const envp) {
  // Run LLC to convert the bytecode file into assembly code.
  const char *cmd[6];
  cmd[0] = llc.c_str();
  cmd[1] = "-f";
  cmd[2] = "-o";
  cmd[3] = OutputFilename.c_str();
  cmd[4] = InputFilename.c_str();
  cmd[5] = 0;

  return ExecWait(cmd, envp);
}

/// GenerateAssembly - generates a native assembly language source file from the
/// specified bytecode file.
int llvm::GenerateCFile(const std::string &OutputFile,
                        const std::string &InputFile,
                        const std::string &llc, char ** const envp) {
  // Run LLC to convert the bytecode file into C.
  const char *cmd[7];

  cmd[0] = llc.c_str();
  cmd[1] = "-march=c";
  cmd[2] = "-f";
  cmd[3] = "-o";
  cmd[4] = OutputFile.c_str();
  cmd[5] = InputFile.c_str();
  cmd[6] = 0;
  return ExecWait(cmd, envp);
}

/// GenerateNative - generates a native assembly language source file from the
/// specified assembly source file.
///
/// Inputs:
///  InputFilename  - The name of the output bytecode file.
///  OutputFilename - The name of the file to generate.
///  Libraries      - The list of libraries with which to link.
///  LibPaths       - The list of directories in which to find libraries.
///  gcc            - The pathname to use for GGC.
///  envp           - A copy of the process's current environment.
///
/// Outputs:
///  None.
///
/// Returns non-zero value on error.
///
int llvm::GenerateNative(const std::string &OutputFilename,
                         const std::string &InputFilename,
                         const std::vector<std::string> &Libraries,
                         const std::vector<std::string> &LibPaths,
                         const std::string &gcc, char ** const envp) {
  // Remove these environment variables from the environment of the
  // programs that we will execute.  It appears that GCC sets these
  // environment variables so that the programs it uses can configure
  // themselves identically.
  //
  // However, when we invoke GCC below, we want it to use its normal
  // configuration.  Hence, we must sanitize its environment.
  char ** clean_env = CopyEnv(envp);
  if (clean_env == NULL)
    return 1;
  RemoveEnv("LIBRARY_PATH", clean_env);
  RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
  RemoveEnv("GCC_EXEC_PREFIX", clean_env);
  RemoveEnv("COMPILER_PATH", clean_env);
  RemoveEnv("COLLECT_GCC", clean_env);

  std::vector<const char *> cmd;

  // Run GCC to assemble and link the program into native code.
  //
  // Note:
  //  We can't just assemble and link the file with the system assembler
  //  and linker because we don't know where to put the _start symbol.
  //  GCC mysteriously knows how to do it.
  cmd.push_back(gcc.c_str());
  cmd.push_back("-fno-strict-aliasing");
  cmd.push_back("-O3");
  cmd.push_back("-o");
  cmd.push_back(OutputFilename.c_str());
  cmd.push_back(InputFilename.c_str());

  // Adding the library paths creates a problem for native generation.  If we
  // include the search paths from llvmgcc, then we'll be telling normal gcc
  // to look inside of llvmgcc's library directories for libraries.  This is
  // bad because those libraries hold only bytecode files (not native object
  // files).  In the end, we attempt to link the bytecode libgcc into a native
  // program.
#if 0
  // Add in the library path options.
  for (unsigned index=0; index < LibPaths.size(); index++) {
    cmd.push_back("-L");
    cmd.push_back(LibPaths[index].c_str());
  }
#endif

  // Add in the libraries to link.
  std::vector<std::string> Libs(Libraries);
  for (unsigned index = 0; index < Libs.size(); index++) {
    if (Libs[index] != "crtend") {
      Libs[index] = "-l" + Libs[index];
      cmd.push_back(Libs[index].c_str());
    }
  }
  cmd.push_back(NULL);

  // Run the compiler to assembly and link together the program.
  return ExecWait(&(cmd[0]), clean_env);
}

<commit_msg>This pass has proven its metal, remove -disable option.<commit_after>//===- GenerateCode.cpp - Functions for generating executable files  ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains functions for generating executable files once linking
// has finished.  This includes generating a shell script to run the JIT or
// a native executable derived from the bytecode.
//
//===----------------------------------------------------------------------===//

#include "gccld.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/Linker.h"
#include "Support/SystemUtils.h"
#include "Support/CommandLine.h"
using namespace llvm;

namespace {
  cl::opt<bool>
  DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify intermediate results of all passes"));

  cl::opt<bool>
  DisableOptimizations("disable-opt",
                       cl::desc("Do not run any optimization passes"));
}

/// CopyEnv - This function takes an array of environment variables and makes a
/// copy of it.  This copy can then be manipulated any way the caller likes
/// without affecting the process's real environment.
///
/// Inputs:
///  envp - An array of C strings containing an environment.
///
/// Return value:
///  NULL - An error occurred.
///
///  Otherwise, a pointer to a new array of C strings is returned.  Every string
///  in the array is a duplicate of the one in the original array (i.e. we do
///  not copy the char *'s from one array to another).
///
static char ** CopyEnv(char ** const envp) {
  // Count the number of entries in the old list;
  unsigned entries;   // The number of entries in the old environment list
  for (entries = 0; envp[entries] != NULL; entries++)
    /*empty*/;

  // Add one more entry for the NULL pointer that ends the list.
  ++entries;

  // If there are no entries at all, just return NULL.
  if (entries == 0)
    return NULL;

  // Allocate a new environment list.
  char **newenv = new char* [entries];
  if ((newenv = new char* [entries]) == NULL)
    return NULL;

  // Make a copy of the list.  Don't forget the NULL that ends the list.
  entries = 0;
  while (envp[entries] != NULL) {
    newenv[entries] = new char[strlen (envp[entries]) + 1];
    strcpy (newenv[entries], envp[entries]);
    ++entries;
  }
  newenv[entries] = NULL;

  return newenv;
}

/// RemoveEnv - Remove the specified environment variable from the environment
/// array.
///
/// Inputs:
///  name - The name of the variable to remove.  It cannot be NULL.
///  envp - The array of environment variables.  It cannot be NULL.
///
/// Notes:
///  This is mainly done because functions to remove items from the environment
///  are not available across all platforms.  In particular, Solaris does not
///  seem to have an unsetenv() function or a setenv() function (or they are
///  undocumented if they do exist).
///
static void RemoveEnv(const char * name, char ** const envp) {
  for (unsigned index=0; envp[index] != NULL; index++) {
    // Find the first equals sign in the array and make it an EOS character.
    char *p = strchr (envp[index], '=');
    if (p == NULL)
      continue;
    else
      *p = '\0';

    // Compare the two strings.  If they are equal, zap this string.
    // Otherwise, restore it.
    if (!strcmp(name, envp[index]))
      *envp[index] = '\0';
    else
      *p = '=';
  }

  return;
}

static inline void addPass(PassManager &PM, Pass *P) {
  // Add the pass to the pass manager...
  PM.add(P);

  // If we are verifying all of the intermediate steps, add the verifier...
  if (Verify) PM.add(createVerifierPass());
}

/// GenerateBytecode - generates a bytecode file from the specified module.
///
/// Inputs:
///  M           - The module for which bytecode should be generated.
///  Strip       - Flags whether symbols should be stripped from the output.
///  Internalize - Flags whether all symbols should be marked internal.
///  Out         - Pointer to file stream to which to write the output.
///
/// Returns non-zero value on error.
///
int llvm::GenerateBytecode(Module *M, bool Strip, bool Internalize,
                           std::ostream *Out) {
  // In addition to just linking the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  PassManager Passes;

  if (Verify) Passes.add(createVerifierPass());

  // Add an appropriate TargetData instance for this module...
  addPass(Passes, new TargetData("gccld", M));

  // Often if the programmer does not specify proper prototypes for the
  // functions they are calling, they end up calling a vararg version of the
  // function that does not get a body filled in (the real function has typed
  // arguments).  This pass merges the two functions.
  addPass(Passes, createFunctionResolvingPass());

  if (!DisableOptimizations) {
    if (Internalize) {
      // Now that composite has been compiled, scan through the module, looking
      // for a main function.  If main is defined, mark all other functions
      // internal.
      addPass(Passes, createInternalizePass());
    }

    // Now that we internalized some globals, see if we can mark any globals as
    // being constant!
    addPass(Passes, createGlobalConstifierPass());

    // Linking modules together can lead to duplicated global constants, only
    // keep one copy of each constant...
    addPass(Passes, createConstantMergePass());

    // If the -s command line option was specified, strip the symbols out of the
    // resulting program to make it smaller.  -s is a GCC option that we are
    // supporting.
    if (Strip)
      addPass(Passes, createSymbolStrippingPass());

    // Propagate constants at call sites into the functions they call.
    addPass(Passes, createIPConstantPropagationPass());

    // Remove unused arguments from functions...
    addPass(Passes, createDeadArgEliminationPass());

    if (!DisableInline)
      addPass(Passes, createFunctionInliningPass()); // Inline small functions

    addPass(Passes, createPruneEHPass());            // Remove dead EH info
    addPass(Passes, createGlobalDCEPass());          // Remove dead functions

    // If we didn't decide to inline a function, check to see if we can
    // transform it to pass arguments by value instead of by reference.
    addPass(Passes, createArgumentPromotionPass());

    // The IPO passes may leave cruft around.  Clean up after them.
    addPass(Passes, createInstructionCombiningPass());

    addPass(Passes, createScalarReplAggregatesPass()); // Break up allocas

    // Run a few AA driven optimizations here and now, to cleanup the code.
    addPass(Passes, createGlobalsModRefPass());      // IP alias analysis

    addPass(Passes, createLICMPass());               // Hoist loop invariants
    addPass(Passes, createLoadValueNumberingPass()); // GVN for load instrs
    addPass(Passes, createGCSEPass());               // Remove common subexprs
    addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores

    // Cleanup and simplify the code after the scalar optimizations.
    addPass(Passes, createInstructionCombiningPass());

    // Delete basic blocks, which optimization passes may have killed...
    addPass(Passes, createCFGSimplificationPass());

    // Now that we have optimized the program, discard unreachable functions...
    addPass(Passes, createGlobalDCEPass());
  }

  // Make sure everything is still good.
  Passes.add(createVerifierPass());

  // Add the pass that writes bytecode to the output file...
  addPass(Passes, new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M);

  return 0;
}

/// GenerateAssembly - generates a native assembly language source file from the
/// specified bytecode file.
///
/// Inputs:
///  InputFilename  - The name of the output bytecode file.
///  OutputFilename - The name of the file to generate.
///  llc            - The pathname to use for LLC.
///  envp           - The environment to use when running LLC.
///
/// Return non-zero value on error.
///
int llvm::GenerateAssembly(const std::string &OutputFilename,
                           const std::string &InputFilename,
                           const std::string &llc,
                           char ** const envp) {
  // Run LLC to convert the bytecode file into assembly code.
  const char *cmd[6];
  cmd[0] = llc.c_str();
  cmd[1] = "-f";
  cmd[2] = "-o";
  cmd[3] = OutputFilename.c_str();
  cmd[4] = InputFilename.c_str();
  cmd[5] = 0;

  return ExecWait(cmd, envp);
}

/// GenerateAssembly - generates a native assembly language source file from the
/// specified bytecode file.
int llvm::GenerateCFile(const std::string &OutputFile,
                        const std::string &InputFile,
                        const std::string &llc, char ** const envp) {
  // Run LLC to convert the bytecode file into C.
  const char *cmd[7];

  cmd[0] = llc.c_str();
  cmd[1] = "-march=c";
  cmd[2] = "-f";
  cmd[3] = "-o";
  cmd[4] = OutputFile.c_str();
  cmd[5] = InputFile.c_str();
  cmd[6] = 0;
  return ExecWait(cmd, envp);
}

/// GenerateNative - generates a native assembly language source file from the
/// specified assembly source file.
///
/// Inputs:
///  InputFilename  - The name of the output bytecode file.
///  OutputFilename - The name of the file to generate.
///  Libraries      - The list of libraries with which to link.
///  LibPaths       - The list of directories in which to find libraries.
///  gcc            - The pathname to use for GGC.
///  envp           - A copy of the process's current environment.
///
/// Outputs:
///  None.
///
/// Returns non-zero value on error.
///
int llvm::GenerateNative(const std::string &OutputFilename,
                         const std::string &InputFilename,
                         const std::vector<std::string> &Libraries,
                         const std::vector<std::string> &LibPaths,
                         const std::string &gcc, char ** const envp) {
  // Remove these environment variables from the environment of the
  // programs that we will execute.  It appears that GCC sets these
  // environment variables so that the programs it uses can configure
  // themselves identically.
  //
  // However, when we invoke GCC below, we want it to use its normal
  // configuration.  Hence, we must sanitize its environment.
  char ** clean_env = CopyEnv(envp);
  if (clean_env == NULL)
    return 1;
  RemoveEnv("LIBRARY_PATH", clean_env);
  RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
  RemoveEnv("GCC_EXEC_PREFIX", clean_env);
  RemoveEnv("COMPILER_PATH", clean_env);
  RemoveEnv("COLLECT_GCC", clean_env);

  std::vector<const char *> cmd;

  // Run GCC to assemble and link the program into native code.
  //
  // Note:
  //  We can't just assemble and link the file with the system assembler
  //  and linker because we don't know where to put the _start symbol.
  //  GCC mysteriously knows how to do it.
  cmd.push_back(gcc.c_str());
  cmd.push_back("-fno-strict-aliasing");
  cmd.push_back("-O3");
  cmd.push_back("-o");
  cmd.push_back(OutputFilename.c_str());
  cmd.push_back(InputFilename.c_str());

  // Adding the library paths creates a problem for native generation.  If we
  // include the search paths from llvmgcc, then we'll be telling normal gcc
  // to look inside of llvmgcc's library directories for libraries.  This is
  // bad because those libraries hold only bytecode files (not native object
  // files).  In the end, we attempt to link the bytecode libgcc into a native
  // program.
#if 0
  // Add in the library path options.
  for (unsigned index=0; index < LibPaths.size(); index++) {
    cmd.push_back("-L");
    cmd.push_back(LibPaths[index].c_str());
  }
#endif

  // Add in the libraries to link.
  std::vector<std::string> Libs(Libraries);
  for (unsigned index = 0; index < Libs.size(); index++) {
    if (Libs[index] != "crtend") {
      Libs[index] = "-l" + Libs[index];
      cmd.push_back(Libs[index].c_str());
    }
  }
  cmd.push_back(NULL);

  // Run the compiler to assembly and link together the program.
  return ExecWait(&(cmd[0]), clean_env);
}

<|endoftext|>


<commit_before>/*
* Copyright (c) The Shogun Machine Learning Toolbox
* Written (w) 2014 Abhijeet Kislay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those
* of the authors and should not be interpreted as representing official policies,
* either expressed or implied, of the Shogun Development Team.
*/
#include <shogun/features/DenseFeatures.h>
#include <shogun/features/DataGenerator.h>
#include <shogun/labels/BinaryLabels.h>
#include <shogun/classifier/LDA.h>
#include <gtest/gtest.h>

#ifdef HAVE_EIGEN3
using namespace shogun;
class LDATest: public::testing::Test
{
protected:

	//one setup for all tests.
	LDATest()
	{

		const int num=5;
		const int dims=3;
		const int classes=2;

		//Prepare the data for binary classification using LDA
		SGVector<float64_t> lab(classes*num);
		SGMatrix<float64_t> feat(dims, classes*num);

		feat(0, 0)=-2.81337943903340859;
		feat(0, 1)=-5.75992432468645088;
		feat(0, 2)=-5.4837468813610224;
		feat(0, 3)=-5.47479715849418014;
		feat(0, 4)=-4.39517634372092836;
		feat(0, 5)=-7.99471372898085164;
		feat(0, 6)=-7.10419958637667648;
		feat(0, 7)=-11.4850011467524826;
		feat(0, 8)=-9.67487852616068089;
		feat(0, 9)=-12.3194880071464681;

		feat(1, 0)=-6.56380697737734309;
		feat(1, 1)=-4.64057958297620488;
		feat(1, 2)=-3.59272857618575481;
		feat(1, 3)=-5.53059381299425468;
		feat(1, 4)=-5.16060076449381011;
		feat(1, 5)=11.0022309320050748;
		feat(1, 6)=10.4475375427292914;
		feat(1, 7)=10.3084005680058421;
		feat(1, 8)=10.3517589923186151;
		feat(1, 9)=11.1302375093709944;

		feat(2, 0)=-2.84357574928607937;
		feat(2, 1)=-6.40222758829360661;
		feat(2, 2)=-5.60120216303194862;
		feat(2, 3)=-4.99340782963709628;
		feat(2, 4)=-3.07109471770865472;
		feat(2, 5)=-11.3998413308604079;
		feat(2, 6)=-10.815184022595691;
		feat(2, 7)=-10.2965326042816976;
		feat(2, 8)=-9.49970263899488998;
		feat(2, 9)=-9.25703218159132923;

		for(int i=0; i<classes; ++i)
			for(int j=0; j<num; ++j)
				if(i==0)
					lab[i*num+j]=-1;
				else
					lab[i*num+j]=+1;

		CBinaryLabels* labels=new CBinaryLabels(lab);
		CDenseFeatures<float64_t>* features = new CDenseFeatures<float64_t>(feat);

		//Train the binary classifier.
		CLDA lda(0, features, labels);
		lda.train();

		//Test.
		CRegressionLabels* results=(lda.apply_regression(features));
		projection=results->get_labels();
		w = lda.get_w();
	}
	SGVector<float64_t> projection;
	SGVector<float64_t> w;
};

TEST_F(LDATest, CheckEigenvectors)
{
	// comparing our 'w' against 'w' a.k.a EigenVec of the scipy implementation
	// of Fisher 2 Class LDA here:
	// http://wiki.scipy.org/Cookbook/LinearClassification
	float64_t epsilon=0.00000001;
	EXPECT_NEAR(5.31296094, w[0], epsilon);
	EXPECT_NEAR(40.45747764, w[1], epsilon);
	EXPECT_NEAR(10.81046958, w[2], epsilon);
}

TEST_F(LDATest, CheckProjection)
{
	// No need of checking the binary labels if the following passes.
	float64_t epsilon=0.00000001;
	EXPECT_NEAR(-304.80621346, projection[0], epsilon);
	EXPECT_NEAR(-281.12285949, projection[1], epsilon);
	EXPECT_NEAR(-228.60266985, projection[2], epsilon);
	EXPECT_NEAR(-300.38571766, projection[3], epsilon);
	EXPECT_NEAR(-258.89964153, projection[4], epsilon);
	EXPECT_NEAR(+285.84589701, projection[5], epsilon);
	EXPECT_NEAR(+274.45608852, projection[6], epsilon);
	EXPECT_NEAR(+251.15879527, projection[7], epsilon);
	EXPECT_NEAR(+271.14418463, projection[8], epsilon);
	EXPECT_NEAR(+291.21213655, projection[9], epsilon);
}
#endif //HAVE_EIGEN3
<commit_msg>Fixing LDA_unittest.cc<commit_after>/*
* Copyright (c) The Shogun Machine Learning Toolbox
* Written (w) 2014 Abhijeet Kislay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those
* of the authors and should not be interpreted as representing official policies,
* either expressed or implied, of the Shogun Development Team.
*/
#include <shogun/features/DenseFeatures.h>
#include <shogun/features/DataGenerator.h>
#include <shogun/labels/BinaryLabels.h>
#include <shogun/classifier/LDA.h>
#include <gtest/gtest.h>

#ifdef HAVE_LAPACK
using namespace shogun;
class LDATest: public::testing::Test
{
protected:

	//one setup for all tests.
	LDATest()
	{

		const int num=5;
		const int dims=3;
		const int classes=2;

		//Prepare the data for binary classification using LDA
		SGVector<float64_t> lab(classes*num);
		SGMatrix<float64_t> feat(dims, classes*num);

		feat(0, 0)=-2.81337943903340859;
		feat(0, 1)=-5.75992432468645088;
		feat(0, 2)=-5.4837468813610224;
		feat(0, 3)=-5.47479715849418014;
		feat(0, 4)=-4.39517634372092836;
		feat(0, 5)=-7.99471372898085164;
		feat(0, 6)=-7.10419958637667648;
		feat(0, 7)=-11.4850011467524826;
		feat(0, 8)=-9.67487852616068089;
		feat(0, 9)=-12.3194880071464681;

		feat(1, 0)=-6.56380697737734309;
		feat(1, 1)=-4.64057958297620488;
		feat(1, 2)=-3.59272857618575481;
		feat(1, 3)=-5.53059381299425468;
		feat(1, 4)=-5.16060076449381011;
		feat(1, 5)=11.0022309320050748;
		feat(1, 6)=10.4475375427292914;
		feat(1, 7)=10.3084005680058421;
		feat(1, 8)=10.3517589923186151;
		feat(1, 9)=11.1302375093709944;

		feat(2, 0)=-2.84357574928607937;
		feat(2, 1)=-6.40222758829360661;
		feat(2, 2)=-5.60120216303194862;
		feat(2, 3)=-4.99340782963709628;
		feat(2, 4)=-3.07109471770865472;
		feat(2, 5)=-11.3998413308604079;
		feat(2, 6)=-10.815184022595691;
		feat(2, 7)=-10.2965326042816976;
		feat(2, 8)=-9.49970263899488998;
		feat(2, 9)=-9.25703218159132923;

		for(int i=0; i<classes; ++i)
			for(int j=0; j<num; ++j)
				if(i==0)
					lab[i*num+j]=-1;
				else
					lab[i*num+j]=+1;

		CBinaryLabels* labels=new CBinaryLabels(lab);
		CDenseFeatures<float64_t>* features = new CDenseFeatures<float64_t>(feat);

		//Train the binary classifier.
		CLDA lda(0, features, labels);
		lda.train();

		//Test.
		CRegressionLabels* results=(lda.apply_regression(features));
		projection=results->get_labels();
		w = lda.get_w();
	}
	SGVector<float64_t> projection;
	SGVector<float64_t> w;
};

TEST_F(LDATest, CheckEigenvectors)
{
	// comparing our 'w' against 'w' a.k.a EigenVec of the scipy implementation
	// of Fisher 2 Class LDA here:
	// http://wiki.scipy.org/Cookbook/LinearClassification
	float64_t epsilon=0.00000001;
	EXPECT_NEAR(5.31296094, w[0], epsilon);
	EXPECT_NEAR(40.45747764, w[1], epsilon);
	EXPECT_NEAR(10.81046958, w[2], epsilon);
}

TEST_F(LDATest, CheckProjection)
{
	// No need of checking the binary labels if the following passes.
	float64_t epsilon=0.00000001;
	EXPECT_NEAR(-304.80621346, projection[0], epsilon);
	EXPECT_NEAR(-281.12285949, projection[1], epsilon);
	EXPECT_NEAR(-228.60266985, projection[2], epsilon);
	EXPECT_NEAR(-300.38571766, projection[3], epsilon);
	EXPECT_NEAR(-258.89964153, projection[4], epsilon);
	EXPECT_NEAR(+285.84589701, projection[5], epsilon);
	EXPECT_NEAR(+274.45608852, projection[6], epsilon);
	EXPECT_NEAR(+251.15879527, projection[7], epsilon);
	EXPECT_NEAR(+271.14418463, projection[8], epsilon);
	EXPECT_NEAR(+291.21213655, projection[9], epsilon);
}
#endif //HAVE_LAPACK
<|endoftext|>