Expansion of periodic mesh - cgal

I have send this trough the mailing list but it seems not to be fully working at the moment so I am posting it here instead. The issue I am having is that I am trying to expand a periodic mesh and have it returned in a new c3t3 structure instead of having to save a .mesh file and load it afterwards. For this I have tried modifying the File_medit.h found in the Periodic_3_mesh_3/IO folder but am having a few issues. First of all, the tetrahedrals seem to not be properly added when I call the build_triangulation function although the finite_cell vector has all collected values in it. I am having a similar issue with the border_facets, although in this case I am also not sure what data I am supposed to place in surface_patch_id and if perhaps this is causing the issues. I have included the code I am using bellow. Any help is appreciated.
Regards, Kim
/* ==========================================================================
* Based on CGAL's File_medit.h. See CGAL Periodic_3_mesh_3/IO.
* ==========================================================================*/
#ifndef CGAL_PERIODIC_REPLICATOR_H
#define CGAL_PERIODIC_REPLICATOR_H
#include <CGAL/license/Periodic_3_mesh_3.h>
#include <CGAL/Mesh_3/io_signature.h>
#include <CGAL/Mesh_3/tet_soup_to_c3t3.h>
//
#include <CGAL/array.h>
#include <CGAL/assertions.h>
#include <CGAL/IO/File_medit.h>
#include <boost/unordered_map.hpp>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <cstring>
#include <sstream>
#include <cstring>
#include <map>
namespace CGAL {
namespace periodic_replicator {
/**
* \brief expands a periodic mesh to the c3t3 variable
* \param c3t3_periodic the mesh
* \param occurrence_count the number of copies that are printed
* \param distinguish_copies if set to `true`, each copy is assigned a unique color.
* Otherwise, all domains are drawn with subdomain index-based colors.
* \param rebind if set to `true`, labels of cells are rebinded into [1..nb_of_labels]
* \param c3t3 the output mesh
*/
template <class C3T3_Periodic, class C3T3, bool rebind, bool no_patch> ////template <class C3T3_Periodic>
void replicate_periodic_mesh(const C3T3_Periodic& c3t3_periodic,
int occurrence_count[3],
const bool distinguish_copies,
C3T3& c3t3)
{
#ifdef CGAL_MESH_3_IO_VERBOSE
std::cerr << "Output to medit:\n";
#endif
CGAL_precondition(c3t3_periodic.triangulation().is_1_cover());
typedef CGAL::Mesh_3::Medit_pmap_generator<C3T3_Periodic, rebind, no_patch> Generator;
typedef typename Generator::Cell_pmap Cell_pmap;
typedef typename Generator::Facet_pmap Facet_pmap;
typedef typename Generator::Facet_pmap_twice Facet_pmap_twice;
typedef typename Generator::Vertex_pmap Vertex_pmap;
//Generator().print_twice();
Cell_pmap cell_pmap(c3t3_periodic);
Facet_pmap facet_pmap(c3t3_periodic, cell_pmap);
Facet_pmap_twice facet_pmap_twice(c3t3_periodic, cell_pmap);
Vertex_pmap vertex_pmap(c3t3_periodic, cell_pmap, facet_pmap);
// const Facet_index_property_map_twice& facet_twice_pmap = Facet_index_property_map_twice(),
const bool print_each_facet_twice = false;//Generator().print_twice();
CGAL_precondition(occurrence_count[0] >= 1 && occurrence_count[1] >= 1 && occurrence_count[2] >= 1);
// Periodic typedef
typedef typename C3T3_Periodic::Triangulation Triangulation_periodic;
typedef Triangulation_periodic Tr_periodic;
typedef typename Tr_periodic::Bare_point Bare_point;
typedef typename Tr_periodic::Weighted_point Weighted_point;
typedef typename C3T3_Periodic::Vertex_handle Vertex_handle;
typedef typename C3T3_Periodic::Cell_handle Cell_handle;
typedef typename Tr_periodic::Vertex_iterator Vertex_iterator;
typedef typename C3T3_Periodic::Facet_iterator Facet_iterator;
typedef typename C3T3_Periodic::Cell_iterator Cell_iterator;
typedef typename Tr_periodic::Offset Offset;
const Triangulation_periodic& tr_periodic = c3t3_periodic.triangulation();
// Non-periodic typedef
typedef typename C3T3::Triangulation Triangulation;
typedef Triangulation Tr;
typedef typename Tr::Point Point_3;
typedef std::array<int, 3> Facet; // 3 = id
typedef std::array<int, 5> Tet_with_ref; // first 4 = id, fifth = reference
//
std::vector<Point_3> points;
//std::map<Facet, typename Tr::Cell::Surface_patch_index> border_facets_;
std::map<Facet, typename C3T3::Surface_patch_index> border_facets;
std::vector<Tet_with_ref> finite_cells;
//
int number_of_vertices = static_cast<int>(tr_periodic.number_of_vertices());
int number_of_facets = static_cast<int>(c3t3_periodic.number_of_facets());
int number_of_cells = static_cast<int>(c3t3_periodic.number_of_cells());
// number of reproductions over the different axes
int Ox_rn = ceil(occurrence_count[0]);
int Oy_rn = ceil(occurrence_count[1]);
int Oz_rn = ceil(occurrence_count[2]);
int occ_mult = Ox_rn * Oy_rn * Oz_rn;
#ifdef CGAL_PERIODIC_3_MESH_3_VERBOSE
std::cerr << "Expanding periodic mesh... " << std::endl;
std::cerr << "occurrences over each axis: "
<< Ox_rn << " " << Oy_rn << " " << Oz_rn << std::endl;
std::cerr << number_of_vertices << " vertices" << std::endl;
std::cerr << number_of_facets << " facets" << std::endl;
std::cerr << number_of_cells << " cells" << std::endl;
#endif
std::ofstream os("output_control.mesh");
os << std::setprecision(17);
// Vertices
int medit_number_of_vertices = (Ox_rn + 1) * (Oy_rn + 1) * (Oz_rn + 1) * number_of_vertices;
os << "MeshVersionFormatted 1\n"
<< "Dimension 3\n"
<< "Vertices\n" << medit_number_of_vertices << std::endl;
// Build the set of points that is needed to draw all the elements.
// On each axis, we repeat n+1 times the point, where 'n' is the number of
// instances of the mesh that will be printed over that axis. This is because
// a cell 'c' might have point(c,i) that is equal to v with an offset 2
boost::unordered_map<Vertex_handle, int> V;
int inum = 1; // '1' because medit ids start at 1
for(int i=0; i<=Oz_rn; ++i) {
for(int j=0; j<=Oy_rn; ++j) {
for(int k=0; k<=Ox_rn; ++k) {
for(Vertex_iterator vit = tr_periodic.vertices_begin(); vit != tr_periodic.vertices_end(); ++vit) {
if(i == 0 && j == 0 && k == 0)
V[vit] = inum++;
const Offset off(k, j, i);
const Weighted_point& p = tr_periodic.point(vit);
const Bare_point bp = tr_periodic.construct_point(p, off);
int id;
if(i >= 1 || j >= 1 || k >= 1)
id = 7;
else
id = tr_periodic.off_to_int(off);
os << CGAL::to_double(bp.x()) << ' '
<< CGAL::to_double(bp.y()) << ' '
<< CGAL::to_double(bp.z()) << ' ';
if(!distinguish_copies || occ_mult == 1)
os << get(vertex_pmap, vit) << '\n';
else
os << 32 * id + 1 << '\n';
points.push_back(Point_3(CGAL::to_double(bp.x()),
CGAL::to_double(bp.y()),
CGAL::to_double(bp.z())));
}
}
}
}
// Triangles
int medit_number_of_triangles = occ_mult * number_of_facets;
if(print_each_facet_twice)
medit_number_of_triangles *= 2;
os << "Triangles\n" << medit_number_of_triangles << std::endl;
for(int i=0; i<Oz_rn; ++i) {
for(int j=0; j<Oy_rn; ++j) {
for(int k=0; k<Ox_rn; ++k) {
const Offset off(k, j, i);
for(Facet_iterator fit = c3t3_periodic.facets_begin(); fit != c3t3_periodic.facets_end(); ++fit) {
typename Tr::Cell::Surface_patch_index surface_patch_id;
Facet facet;
for(int l=0; l<4; ++l) {
if(l == fit->second)
continue;
Cell_handle c = fit->first;
Vertex_handle v = c->vertex(l);
const Offset combined_off = tr_periodic.combine_offsets(
off, tr_periodic.int_to_off(c->offset(l)));
const int vector_offset = combined_off.x() +
combined_off.y() * (Ox_rn + 1) +
combined_off.z() * (Ox_rn + 1) * (Oy_rn + 1);
const int id = vector_offset * number_of_vertices + V[v];
CGAL_assertion(1 <= id && id <= medit_number_of_vertices);
os << id << " ";
//facet[l] = id;
int temp_ = id;
facet[l] = temp_;
}
// For multiple copies, color to distinguish copies rather than to distinguish subdomains
//int temptest;
if(!distinguish_copies || occ_mult == 1){
os << get(facet_pmap, *fit) << '\n';
} else {
os << 1 + k + 3*j + 9*i << '\n';
}
surface_patch_id.first = 0;
surface_patch_id.second = 1;
border_facets.insert(std::make_pair(facet, surface_patch_id));
// Print triangle again if needed
if(print_each_facet_twice) {
for(int l=0; l<4; ++l) {
if(l == fit->second)
continue;
Cell_handle c = fit->first;
Vertex_handle v = c->vertex(l);
const Offset combined_off = tr_periodic.combine_offsets(
off, tr_periodic.int_to_off(c->offset(l)));
const int vector_offset = combined_off.x() +
combined_off.y() * (Ox_rn + 1) +
combined_off.z() * (Ox_rn + 1) * (Oy_rn + 1);
const int id = vector_offset * number_of_vertices + V[v];
CGAL_assertion(1 <= id && id <= medit_number_of_vertices);
os << id << " ";
int temp_ = id;
facet[l] = temp_;
}
if(!distinguish_copies || occ_mult == 1)
os << get(facet_pmap_twice, *fit) << '\n';
else
os << 1 + k + 3*j + 9*i << '\n';
//surface_patch_id = ???;
//border_facets.insert(std::make_pair(facet, surface_patch_id));
}
}
}
}
}
// Tetrahedra
os << "Tetrahedra\n" << occ_mult * number_of_cells << std::endl;
for(int i=0; i<Oz_rn; ++i) {
for(int j=0; j<Oy_rn; ++j) {
for(int k=0; k<Ox_rn; ++k) {
const Offset off(k, j, i);
for(Cell_iterator cit = c3t3_periodic.cells_begin(); cit !=c3t3_periodic.cells_end(); ++cit) {
Tet_with_ref t;
for(int l=0; l<4; ++l) {
const Offset combined_off = tr_periodic.combine_offsets(
off, tr_periodic.int_to_off(cit->offset(l)));
const int vector_offset = combined_off.x() +
combined_off.y() * (Ox_rn + 1) +
combined_off.z() * (Ox_rn + 1) * (Oy_rn + 1);
const int id = vector_offset * number_of_vertices + V[cit->vertex(l)];
CGAL_assertion(1 <= id && id <= medit_number_of_vertices);
os << id << " ";
t[l] = id - 1;
}
// For multiple copies, color to distinguish copies rather than to distinguish subdomains
if(!distinguish_copies || occ_mult == 1) {
os << get(cell_pmap, cit) << '\n';
t[4] = get(cell_pmap, cit);
} else {
os << 1 + k + 3*j + 9*i << '\n';
t[4] = 1 + k + 3*j + 9*i;
}
finite_cells.push_back(t);
}
}
}
}
os << "End" << std::endl;
//
//std::vector<typename Tr::Vertex_handle> vertices(0);
std::vector<typename Tr::Vertex_handle> vertices(points.size() + 1);
bool is_well_built = build_triangulation<Tr, true>(c3t3.triangulation(), points, finite_cells, border_facets, vertices, true/*verbose*/, false/*replace_domain*/);
// Check
std::cout << points.size() << " points" << std::endl;
std::cout << border_facets.size() << " border facets" << std::endl;
std::cout << finite_cells.size() << " cells" << std::endl;
std::cout << c3t3.number_of_facets() << " border facets expanded c3t3" << std::endl;
std::cout << c3t3.number_of_cells() << " cells expanded c3t3" << std::endl;
}
#ifdef CGAL_MESH_3_IO_VERBOSE
std::cerr << "done.\n";
#endif
} // namespace periodic_replicator
} // namespace CGAL
#endif // CGAL_PERIODIC_REPLICATOR_H

Related

Degraded performance of CGAL::intersection between a 32 bit and 64 bit application while multi-threading

We have recently changed our application from 32 bit to 64 bit and have noticed a degradation in performance when using CGAL::intersection in multiple worker threads. Each thread is using a distinct set of shapes, and so do not interfere with each other.
Here is a simple example I put together to illustrate the issue:
#include <iostream>
#include <vector>
#include <thread>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Gps_circle_segment_traits_2.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Gps_circle_segment_traits_2<Kernel> Traits_2;
typedef Kernel::Point_2 Point_2;
typedef Traits_2::General_polygon_2 Polygon_2;
typedef Traits_2::General_polygon_with_holes_2 Polygon_with_holes_2;
typedef Traits_2::X_monotone_curve_2 X_monotone_curve_2;
const bool multiThreading = true;
const int threadCount = 7;
const int attempts = 2520;
const int overallAttempts = 10;
Polygon_2 construct_polygon(const Point_2& p1, const Point_2& p2, const Point_2& p3, const Point_2& p4, const Point_2& p5)
{
Polygon_2 pgn;
X_monotone_curve_2 s1(p1, p2); pgn.push_back(s1);
X_monotone_curve_2 s2(p2, p3); pgn.push_back(s2);
X_monotone_curve_2 s3(p3, p4); pgn.push_back(s3);
X_monotone_curve_2 s4(p4, p5); pgn.push_back(s4);
X_monotone_curve_2 s5(p5, p1); pgn.push_back(s5);
return pgn;
}
void do_intersection()
{
Polygon_2 outerPolygon = construct_polygon(Point_2(0, 0), Point_2(300, 0), Point_2(310, 150), Point_2(300, 300), Point_2(0, 300));
int numHoles = 100;
std::vector<Polygon_2> holes(numHoles);
for (int i = 0; i < numHoles; i++)
{
holes[i] = construct_polygon(Point_2(2 * i + 1, 2 * i + 1), Point_2(2 * i + 1, 2 * i + 1.5), Point_2(2 * i + 2, 2 * i + 2), Point_2(2 * i + 5, 2 * i + 2), Point_2(2 * i + 3, 2 * i + 1));
}
Polygon_with_holes_2 p(outerPolygon, holes.begin(), holes.end());
Polygon_2 poly1 = construct_polygon(Point_2(1, 0), Point_2(50, 1), Point_2(12, 13), Point_2(25, 50), Point_2(12, 100));
int intersectAttempts = multiThreading ? attempts / threadCount : attempts;
for (int i = 0; i < intersectAttempts; i++)
{
std::list<Polygon_with_holes_2> intersect;
CGAL::intersection(p, poly1, std::back_inserter(intersect));
}
}
int main(int argc, char* argv[])
{
long long averageTime = 0;
for (int x = 0; x < overallAttempts; x++)
{
auto startTime = std::chrono::high_resolution_clock::now();
if (multiThreading)
{
std::thread threads[threadCount];
for (int i = 0; i < threadCount; i++)
{
threads[i] = std::thread(do_intersection);
}
for (int i = 0; i < threadCount; i++)
{
threads[i].join();
}
}
else
{
do_intersection();
}
auto endTime = std::chrono::high_resolution_clock::now();
auto diffTime = endTime - startTime;
averageTime = averageTime + diffTime.count();
std::cout << "Total cost: " << diffTime.count() * 1e-9 << std::endl;
}
std::cout << std::endl;
std::cout << "Average cost: " << (averageTime * 1e-9)/overallAttempts << std::endl;
return 0;
}
When using a single thread, this example is roughly 15% faster in x64 than in x86. However when using 7 worker threads (my machine has 8 logical processors), this example is roughly 50% slower in x64 than x86.
We are unsure why this is considerably slower, but i think it may be related to using CGAL::intersection on a polygon with a lot of holes. Any helpful suggestions would be greatly appreciated.

Threads indexing out of bounds in CUDA kernel

I am running a CUDA kernel which seems to be indexing out of bounds and I can not figure out why. I get error 8 write-of-size in cuda-memcheck.
I have tried to change the number of blocks and the number of threads in each block as well as only running a fraction of all iterations needed. Here is some usefull information as well as a replicable example which gives the error:
blockSize: 128
numBlocks: 512
Nvidia GTX 970
#include <iostream>
#include <cuda_runtime_api.h>
#include <cuda.h>
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <vector>
#include <iterator>
#include <cuda_profiler_api.h>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <stdio.h>
#include <fstream>
__host__
int NchooseK(const int &N, const int &K)
{
int result = 1;
for (int i = 1; i <= K; i++)
{
result *= N - (K - i);
result /= i;
}
return result;
}
__host__
inline int get_flatten_size(const unsigned int N){
int sum = 0;
for(int i=1; i<=N ; i++){
sum +=i*NchooseK(N,i);
}
return sum;
}
__host__
std::vector<int> comb(const int &N, const int &K, const int &length)
//void comb(int N, int K, int length)
{
int k;
std::vector<int> vec(K);
std::vector<int> flatten_vec(0);
std::string bitmask(K, 1); // K leading 1's
bitmask.resize(N, 0); // N-K trailing 0's
for (int j = 0; j < length; j++) {
k = 0;
for (int i = 0; i < N; ++i) // [0..N-1] integers
{
if (bitmask[i]) {
//std::cout << i << " ";
vec[k] = i;
k++;
}
//std::cout << std::endl;
}
std::prev_permutation(bitmask.begin(), bitmask.end());
flatten_vec.insert(flatten_vec.end(), vec.begin(),vec.end());
}
return flatten_vec;
}
__host__
void get_matrix_indices(const unsigned int N, int *sub_col, int *sub_size, int *cumulative_size)
{
int size, itterator = 0;
cumulative_size[0] = 0;
std::vector<int> size_i_columns;
std::vector<int> all_columns(0);
for(int i=1; i<=N; i++){
size = NchooseK(N,i);
size_i_columns = comb(N,i,size);
for(int j=0; j<size; j++){
sub_size[itterator]=i;
cumulative_size[itterator+1]=cumulative_size[itterator]+i;
itterator++;
}
all_columns.insert(all_columns.end(),size_i_columns.begin(),size_i_columns.end());
}
//sub_col = &all_columns[0];
for(int i = 0; i < all_columns.size(); i++) sub_col[i] = all_columns[i];
}
__global__
void comb_ols(const unsigned int M, const unsigned int N, int* sub_col, int *sub_size, int* cumulative_size, const unsigned int numberOfCalculations, const unsigned int max_size){
int size;
int start_index;
int index = blockIdx.x*blockDim.x+threadIdx.x;
int stride = blockDim.x*gridDim.x;
double *sub_matrix = new double[M*(1+max_size)];
for(int i = index; i < numberOfCalculations; i+=stride){
size = sub_size[i];
start_index = cumulative_size[i];
for(int j = 0; j < size; j++){
for(int k = 0; k<M; k++){
sub_matrix[k] = 1;
}
}
}
delete [] sub_matrix;
}
And then we the main function:
int main()
{
int N = 17;
int M = 263;
const unsigned int regressors = N-1;
const unsigned int numberOfCalculations = (int) (exp2((double) regressors) - 1);
const unsigned int size_sub_col = get_flatten_size(regressors);
int blockSize =128;
int numBlocks = (numberOfCalculations + blockSize-1)/blockSize;
std::cout << "\nblockSize :" << blockSize;
std::cout << "\nnumBlocks :" << numBlocks;
std::cout << "\nblockSize*numBlocks :" << blockSize*numBlocks;
std::cout << "\nregressors :" << regressors;
std::cout << "\nNumberOfCalculations :" << numberOfCalculations;
std::cout << "\nsize_sub_col :" << size_sub_col << '\n' ;
int *sub_size, *cumulative_size, *sub_columns;
cudaMallocManaged(&sub_size, numberOfCalculations*sizeof(int));
cudaMallocManaged(&cumulative_size, (numberOfCalculations+1)*sizeof(int));
cudaMallocManaged(&sub_columns, size_sub_col*sizeof(int));
get_matrix_indices(regressors,sub_columns, sub_size, cumulative_size);
const unsigned int max_size = N*M;
cudaProfilerStart();
comb_ols<<<numBlocks, blockSize>>>(M,N,sub_columns, sub_size, cumulative_size, numberOfCalculations, max_size);
cudaProfilerStop();
cudaDeviceSynchronize();
cudaFree(sub_size);
cudaFree(cumulative_size);
cudaFree(sub_columns);
return 0;
}
I fail to see why the threads would try to access illegal memory space. The way I understood is that the matrix sub_matrix will be initilized on each thread once and then the parallel for loop happens. Thus should each thread have the necessary memory space. Am I allocating too much memory on the GPU? How is "new sub_matrix" handled here?
If I read your code correctly, each thread is attempting to allocate M * (1 + M*N) doubles, which is 263 * ( 1 + 263*17) = ‭1,176,136‬ doubles, or 8.97Mb of heap memory per thread. You launch 128 * 512 threads. That would mean you require 588Gb of heap space for the kernel to run successfully.
Clearly your GPU lacks that amount of memory and the out of bounds memory access comes from failures in the new call (which you can check for, BTW).
Might I suggest that something in the size calculations for the heap memory you require is wrong. Otherwise you have an extremely unrealistic problem for the GPU and will require some other approach.
Note that even if you manage to redesign things to limit the code to a feasible malloc heap memory size, you will still need, in all likelihood, to resize the malloc heap to a suitable size before running the kernel. The cudaDeviceSetLimit API can be used for this.

How to generate binary tree dot file for Graphviz from C++

I have implemented a Binary Search Tree in C++ which support dynamically creating and deleting nodes. To visualize the tree, I firstly tried displaying edges with / and \. However, this gives really awful visualization, as the position of / and \ needs to be calculated precisely. The current figures are as follows:
So I found a tool called Graphviz. The raw language supported by Graphviz is dot language, which I am not familiar with.
I read the documentation and found the dot language easy to write and read, but I still want to use my C++ code to generate the tree as this contains much content such as inserting according to user's input.
Is there any chance to use some function to generate the dot file?
The code of my binary tree:
//BTNode.h
#include <iostream>
using namespace std;
template<class T>
struct BTNode{
BTNode(){
lChild = rChild = NULL;
}
BTNode(const T& x){
element = x;
lChild = rChild = NULL;
}
BTNode(const T& x, BTNode<T>* l, BTNode<T>* r){
element = x;
lChild = l;
rChild = r;
}
T element;
int digit, row;
BTNode<T>* lChild, *rChild;
};
//BSTree.h
#include"ResultCode.h"
#include "BTNode.h"
#include "seqqueue.h"
#include <math.h>
template <class T>
class BSTree
{
public:
BSTree(){ root = NULL; }
ResultCode SearchByRecursion(T& x)const;
ResultCode Insert(T& x);
ResultCode Remove(T& x);
void InOrder(void(*Visit)(T& x));
ResultCode SearchByIteration(T& x);
void GradeOrder(void(*Visit)(T &x), BTNode<T> *t, int height);
BTNode<T>* root;
void printSpace(int num);
int GetHeight();
int GetHeight(BTNode<T> *t);
int **A;
private:
ResultCode SearchByRecursion(BTNode<T> *p, T& x)const;
void InOrder(void(*Visit)(T& x), BTNode<T> *t);
};
template <class T>
ResultCode BSTree<T>::SearchByRecursion(T &x)const{
return SearchByRecursion(root, x);
}
template <class T>
ResultCode BSTree<T>::SearchByRecursion(BTNode<T> *p, T& x)const{
if (!p) return NotPresent;
else if (x < p->element) return SearchByRecursion(p->lChild, x);
else if (x > p->element) return SearchByRecursion(p->rChild, x);
else{
x = p->element;
return Success;
}
}
template <class T>
ResultCode BSTree<T>::SearchByIteration(T& x){
BTNode<T> *p = root;
while (p)
if (x < p->element) p = p->lChild;
else if (x > p->element) p = p->rChild;
else{
x = p->element;
return Success;
}
return NotPresent;
}
template<class T>
ResultCode BSTree<T>::Insert(T& x){
BTNode<T> *p = root, *q = NULL;
while (p){
q = p;
if (x < p->element) p = p->lChild;
else if (x > p->element) p = p->rChild;
else { x = p->element; return Duplicate; }
}
p = new BTNode<T>(x);
if (!root) root = p;
else if (x < q->element) q->lChild = p;
else q->rChild = p;
return Success;
}
template <class T>
ResultCode BSTree<T>::Remove(T& x){
BTNode<T> *c, *s, *r, *p = root, *q = NULL;
while (p && p->element != x){
q = p;
if (x < p->element) p = p->lChild;
else p = p->rChild;
}
if (!p) return NotPresent;
x = p->element;
if (p->lChild&&p->rChild)
{
s = p->rChild;
r = p;
while (s->lChild){
r = s; s = s->lChild;
}
p->element = s->element;
p = s; q = r;
}
if (p->lChild)
c = p->lChild;
else c = p->rChild;
if (p == root)
root = c;
else if (p == q->lChild)
q->lChild = c;
else q->rChild = c;
delete p;
return Success;
}
template <class T>
void BSTree<T>::InOrder(void(*Visit)(T &x)){
InOrder(Visit, root);
}
template <class T>
void BSTree<T>::InOrder(void(*Visit)(T &x), BTNode<T> *t){
if (t){
InOrder(Visit, t->lChild);
Visit(t->element);
InOrder(Visit, t->rChild);
}
}
template <class T>
void BSTree<T>::GradeOrder(void(*Visit)(T &x), BTNode<T> *t, int height)
{
A = new int*[height];
for (int i = 0; i < height; i++){
A[i] = new int[(int)pow(2, height) - 1];
}
for (int i = 0; i < height; i++)
for (int j = 0; j < (int)pow(2, height) - 1; j++){
A[i][j] = -1;
}
SeqQueue<BTNode<T>*> OrderQueue(10);
BTNode<T> * loc = t;
loc->row = 0;
loc->digit = 0;
if (loc){
OrderQueue.EnQueue(loc);
A[loc->row][loc->digit] = loc->element;
}
while (!OrderQueue.IsEmpty())
{
OrderQueue.Front(loc);
OrderQueue.DeQueue();
if (loc->lChild)
{
A[(loc->row) + 1][2 * (loc->digit)] = loc->lChild->element;
loc->lChild->row = (loc->row) + 1;
(loc->lChild->digit) = (loc->digit) * 2;
OrderQueue.EnQueue(loc->lChild);
}
if (loc->rChild)
{
A[(loc->row) + 1][2 * (loc->digit) + 1] = loc->rChild->element;
loc->rChild->row = (loc->row) + 1;
(loc->rChild->digit) = (loc->digit) * 2 + 1;
OrderQueue.EnQueue(loc->rChild);
}
}
cout << endl;
int total = (int)(pow(2, height)) - 1;
for (int i = 0; i < height; i++){
if (i != 0){
cout << endl;
}
int space1 = (total / (int)(pow(2, i + 1)));
int space2;
if (i == 0){
space2 = 0;
}
else{
space2 = (total - 2 * space1 - (int)pow(2, i)) / (int)(pow(2, i) - 1);
}
printSpace(space1);
for (int j = 0; j < (int)pow(2, i); j++){
if (A[i][j] != -1){
cout << A[i][j];
}
else{
cout << " ";
}
printSpace(space2);
}
printSpace(space1);
cout << endl;
}
}
template <class T>
void BSTree<T>::printSpace(int num){
for (int i = 0; i < num; i++){
cout << " ";
}
}
template<class T>
int BSTree<T>::GetHeight()
{
return GetHeight(root);
}
template<class T>
int BSTree<T>::GetHeight(BTNode<T> *t)
{
if (!t)return 0;
if ((!t->lChild) && (!t->rChild)) return 1;
int lHeight = GetHeight(t->lChild);
int rHeight = GetHeight(t->rChild);
return (lHeight > rHeight ? lHeight : rHeight) + 1;
}
template <class T>
void Visit(T& x){
cout << x << " ";
}
//main.cpp
#include <iostream>
#include "BSTree4.h"
#include<Windows.h>
int getDigit(int x);
int main(){
BSTree<int> bt;
int number;
// char choice;
cout << "Welcome to BSTree System, to begin with, you need to create a tree!(Press enter to continue...)" << endl;
getchar();
cout << "Please enter the size of the Binary Search Tree:";
cin >> number;
int *ToBeInserted = new int[number];
cout << "Enter the number of each Node(size:" << number << "):";
for (int i = 0; i < number; i++){
cin >> ToBeInserted[i];
}
cout << "OK,now the tree will be created!" << endl;
for (int i = 0; i < number; i++){
cout << "Inserting Node " << i;
for (int k = 0; k < 3; k++){
cout << ".";
//Sleep(200);
}
showResultCode(bt.Insert(ToBeInserted[i]));
//Sleep(500);
}
cout << "Done." << endl;
//Sleep(500);
int height = bt.GetHeight();
bt.GradeOrder(Visit, bt.root,height);
int a;
cout << "please enter the number to search:";
cin>>a;
showResultCode(bt.SearchByRecursion(a));
bt.GradeOrder(Visit, bt.root,height);
if (bt.SearchByRecursion(a) == 7){
cout << "Now delete the number" << "..." << endl;
showResultCode(bt.Remove(a));
bt.GetHeight();
cout << "Deleted!Now the tree is:" << endl;
bt.GradeOrder(Visit, bt.root, height);
bt.InOrder(Visit);
cout << endl;
}
return 0;
}
//resultcode.h
#include<iostream>
using namespace std;
enum ResultCode{ NoMemory, OutOfBounds, Underflow, Overflow, Failure,
NotPresent, Duplicate, Success };
void showResultCode(ResultCode result)
{
int r = (int)result;
switch (result)
{
case 0:cout << "NoMemory" << endl; break;
case 1:cout << "OutOfBounds" << endl; break;
case 2:cout << "Underflow" << endl; break;
case 3:cout << "Overflow" << endl; break;
case 4:cout << "Failure" << endl; break;
case 5:cout << "NotPresent" << endl; break;
case 6:cout << "Duplicate" << endl; break;
case 7:cout << "Success" << endl; break;
default: cout << "Exception occured:unknown resultcode" << endl;
}
}
Update: I have solved the problem myself, check the answer below.
The key elements in dot language file in this problem are nodes and edges. Basically the dot file structure for a binary tree would be like the following:
digraph g {
//all the nodes
node0[label="<f0>|<f1> value |<f2>"]
node1[label="<f0>|<f1> value |<f2>"]
node2[label="<f0>|<f1> value |<f2>"]
...
//all the edges
"node0":f2->"node4":f1;
"node0":f0->"node1":f1;
"node1":f0->"node2":f1;
"node1":f2->"node3":f1;
...
}
The following output of the dot file can be used to understand the structure:
Explanation for the dot file:
For the node part node0[label="<f0>|<f1> value |<f2>"] means the node called node0 has three parts: <f0> is the left part, <f1> is the middle part with a value, <f2> is the right part. This just corresponds to leftchild, value and rightchild in a binary node.
For the edges part, "node0":f2->"node4":f1; means the right part of node0(i.e.<f2>) points to the middle part of node4 (i.e. <f1>).
Therefore, the way to generate the dot file is simply through a traverse of a binary tree. Any method is fine. (BFS,DFS...) All we need is to add the code to write the nodes and corresponding edges into file when we do the traverse. I personally used BFS with level order traverse of a binary tree to implement which is shown below as a function called showTree.
void showTree(BSTree<int> &bst,int total,int *Inserted){
char filename[] = "D:\\a.gv"; // filename
ofstream fout(filename);
fout << "digraph g{" << endl;
fout << "node [shape = record,height = .1];" << endl;
SeqQueue<BTNode<int>*> OrderQueue(1000);
BTNode<int> * loc = bst.root;
loc->row = 0;
loc->digit = 0;
int num = 0;
if (loc){
OrderQueue.EnQueue(loc);
loc->ID = num++;
fout << " node" << loc->ID << "[label = \"<f0> |<f1>" << loc->element << "|<f2>\"];" << endl;
}
while (!OrderQueue.IsEmpty())
{
OrderQueue.Front(loc);
OrderQueue.DeQueue();
if (loc->lChild)
{
loc->lChild->row = (loc->row) + 1;
(loc->lChild->digit) = (loc->digit) * 2;
OrderQueue.EnQueue(loc->lChild);
loc->lChild ->ID= (num++);
fout << " node" << loc->lChild->ID << "[label = \"<f0> |<f1>" << loc->lChild->element << "|<f2>\"];" << endl;
//cout << loc->ID;
}
if (loc->rChild)
{
loc->rChild->row = (loc->row) + 1;
(loc->rChild->digit) = (loc->digit) * 2 + 1;
OrderQueue.EnQueue(loc->rChild);
loc->rChild->ID = (num++);
fout << " node" << loc->rChild->ID << "[label = \"<f0> |<f1>" << loc->rChild->element << "|<f2>\"];" << endl;
//cout << loc->ID;
}
}
//begin to draw!
SeqQueue<BTNode<int>*> OrderQueue2(1000);
BTNode<int> * loc2 = bst.root;
loc2->row = 0;
loc2->digit = 0;
if (loc2){
OrderQueue2.EnQueue(loc2);
}
while (!OrderQueue2.IsEmpty())
{
OrderQueue2.Front(loc2);
OrderQueue2.DeQueue();
if (loc2->lChild)
{
loc2->lChild->row = (loc2->row) + 1;
(loc2->lChild->digit) = (loc2->digit) * 2;
OrderQueue2.EnQueue(loc2->lChild);
cout << "\"node" << loc2->ID << "\":f0->\"node" << loc2->lChild->ID << "\":f1;" << endl;
cout << loc2->lChild->element << endl;
fout << "\"node" << loc2->ID << "\":f0->\"node" << loc2->lChild->ID << "\":f1;" << endl;
}
if (loc2->rChild)
{
loc2->rChild->row = (loc2->row) + 1;
(loc2->rChild->digit) = (loc2->digit) * 2 + 1;
OrderQueue2.EnQueue(loc2->rChild);
cout << "\"node" << loc2->ID << "\":f2->\"node" << loc2->rChild->ID << "\":f1;" << endl;
cout << loc2->rChild->element << endl;
fout << "\"node" << loc2->ID << "\":f2->\"node" << loc2->rChild->ID << "\":f1;" << endl;
}
}
fout << "}" << endl;
}
And the final output:

Visual Studio Error 2784 : could not deduce template argument for GMP from FLINT

I have a problem running the source code of "homomorphic Simon encryption using YASHE and FV leveled homomorphic cryptosystems" (https://github.com/tlepoint/homomorphic-simon) in Visual Studio 2012.
I'm using FLINT 2.5.2, MPIR 2.7.2, MPFR 1.3.1 and getting numerous errors as follows :
#include "stdafx.h"
#include "FVKey.h"
#include "Sampler.h"
#include <iostream>
#include "arith.h"
#include "timing.h"
#include <string>
/* Static values */
fmpzxx W((fmpzxx(1) << WORDLENGTH)); //error C2678
fmpzxx MASKING((fmpzxx(1) << WORDLENGTH)-fmpzxx(1)); //error C2678
/* Print Key */
std::ostream& operator<<(std::ostream& os, const FVKey& k) {
os << "<FVKey with ell=" << k.ell << " num_slots=" << k.get_num_slots() << " q=" << k.q
<< " t=" << k.t << " sigma_key=" << k.sigmakey << " sigma_err=" << k.sigmaerr
<< ">";
return os;
}
/* Small useful functions */
bool isPowerOfTwo(int n)
{
return (n) && !(n & (n - 1)); //this checks if the integer n is a power of two or not
}
void binaryGen(fmpz_mod_polyxx& f, unsigned degree)
{
for (unsigned i=0; i<=degree; i++)
f.set_coeff(i, fmpzxx((rand()%3)-1));
}
fmpz_mod_polyxx FVKey::BitVectorToPoly(BitVector& m)
{
assert(m.l() == num_slots);
if (!batching || num_slots == 1)
{
fmpz_mod_polyxx pf(q);
for (unsigned i=0; i<m.l(); i++)
pf.set_coeff(i, m[i]);
return pf;
}
else
{
fmpz_mod_polyxx pf(t);
fmpz_mod_polyxx mess(t);
mess.set_coeff(0, m[0]);
pf = mess;
for (unsigned i=1; i<num_slots; i++)
{
mess.set_coeff(0, m[i]);
pf = CRT(pf, mess, i-1);
}
fmpz_mod_polyxx result(q);
result = pf.to<fmpz_polyxx>();
return result;
}
}
unsigned noise_from_poly(const fmpz_mod_polyxx& cval, const fmpzxx &q, unsigned ell)
{
unsigned bitnoise = 0;
fmpzxx coeff;
for (unsigned i=0; i<ell; i++)
{
coeff = (cval.get_coeff(i).to<fmpzxx>()); //error C2893 ,C2228,C2059
if (2*coeff > q) //error C2893, error C2784
coeff = coeff - q; //error C2893, error C2784
if (coeff.sizeinbase(2)>bitnoise)
bitnoise = coeff.sizeinbase(2);
}
return bitnoise;
}
/* Constructor */
FVKey::FVKey(const struct FVParams& params, bool batch)
{
// Initializations
n = params.n;
sigmakey = params.sigmakey;
sigmaerr = params.sigmaerr;
q = params.q;
t = params.t;
logwq = q.sizeinbase(2)/WORDLENGTH+1;
qdivt = q/t; //error C2893, error C2784
qdiv2t = q/(2*t); //error C2784
// Define polynomial modulus
arith_cyclotomic_polynomial(poly._data().inner, n);
phi = new fmpz_mod_polyxx(q);
*phi = poly;
ell = phi->degree();
// Factorize the modulus if batching is set
batching = batch;
num_slots = 1;
if (batching)
{
std::cout << "Factorize the cyclotomic polynomial modulo " << t << std::endl;
fmpz_mod_polyxx phimodt(t);
phimodt = poly;
timing T;
T.start();
factors = new fmpz_mod_poly_factorxx(factor_cantor_zassenhaus(phimodt));
T.stop("Factorize");
unsigned degreeFactors = 0;
for (unsigned i=0; i<factors->size(); i++)
{
degreeFactors += factors->p(i).degree();
}
if (degreeFactors == phimodt.degree() && factors->size()>1)
{
std::cout << "Batching possible on " << factors->size() << " slots" << std::endl;
num_slots = factors->size();
invfactors.resize(num_slots-1, fmpz_mod_polyxx(t));
fmpz_mod_polyxx num(t);
num.set_coeff(0, 1);
for (unsigned i=0; i<num_slots-1; i++)
{
num = num*factors->p(i);
invfactors[i] = num.invmod(factors->p(i+1));
}
}
else
{
std::cout << "Batching impossible" << std::endl;
}
}
// Creating sk/pk
std::cerr << "Creating sk/pk" << std::endl;
a = new fmpz_mod_polyxx(q);
s = new fmpz_mod_polyxx(q);
b = new fmpz_mod_polyxx(q);
for (unsigned i=0; i<ell; i++)
{
fmpzxx coeff = fmpzxx(random.getRandomLong());
for (unsigned j=0; j<q.sizeinbase(2)/64; j++)
coeff = (coeff<<64)+fmpzxx(random.getRandomLong());
a->set_coeff(i, coeff);
}
samplerkey = new Sampler(sigmakey*0.4, 1., &random); // 1/sqrt(2*pi) ~ 0.4
if (sigmakey == 1) binaryGen(*s, ell-1);
else
{
for (unsigned i=0; i<ell; i++)
{
long value = samplerkey->SamplerGaussian();
if (value>=0) s->set_coeff(i, fmpzxx(value));
else s->set_coeff(i, q-fmpzxx(-value));
}
}
samplererr = new Sampler(sigmaerr*0.4, 1., &random); // 1/sqrt(2*pi) ~ 0.4
fmpz_mod_polyxx e(q);
if (sigmaerr == 1) binaryGen(e, ell-1);
else
{
for (unsigned i=0; i<ell; i++)
{
long value = samplererr->SamplerGaussian();
if (value>=0) e.set_coeff(i, fmpzxx(value));
else e.set_coeff(i, q-fmpzxx(-value));
}
}
*b = (-((*a)*(*s)%(*phi)))+e;
// Create evaluation key
gamma.resize(2);
gamma[0].resize(logwq, fmpz_mod_polyxx(q));
for (unsigned i=0; i<logwq; i++)
{
for (unsigned j=0; j<ell; j++)
{
fmpzxx coeff = fmpzxx(random.getRandomLong());
for (unsigned k=0; k<q.sizeinbase(2)/64; k++)
coeff = (coeff<<64)+fmpzxx(random.getRandomLong());
gamma[0][i].set_coeff(j, coeff);
}
}
gamma[1].resize(logwq, fmpz_mod_polyxx(q));
for (unsigned i=0; i<logwq; i++)
{
gamma[1][i] = (*s)*(*s);
for (unsigned j=0; j<i; j++)
gamma[1][i] = gamma[1][i]*W;
fmpz_mod_polyxx e2(q);
if (sigmaerr == 1) binaryGen(e2, ell-1);
else
{
for (unsigned i=0; i<ell; i++)
{
long value = samplererr->SamplerGaussian();
if (value>=0) e2.set_coeff(i, fmpzxx(value));
else e2.set_coeff(i, q-fmpzxx(-value));
}
}
gamma[1][i] += (-(gamma[0][i]*(*s)%(*phi)))+e2;
}
}
Error C2784:
'__gmp_expr,mpir_ui,__gmp_binary_multiplies>>
operator *(const __gmp_expr &,unsigned __int64)' : could not
deduce template argument for 'const __gmp_expr &' from
'int' fvkey.cpp 115 Error C2784:
'__gmp_expr,__gmp_binary_multiplies>>
operator *(unsigned short,const __gmp_expr &)' : could not deduce
template argument for 'const __gmp_expr &' from 'flint::fmpzxx'
Error C2784:
'__gmp_expr,__gmp_binary_minus>> operator -(unsigned short,const __gmp_expr &)' : could not deduce
template argument for 'const __gmp_expr &' from 'const
flint::fmpzxx' fvkey.cpp 116
Error C2784:
'__gmp_expr,__gmp_binary_divides>>
operator /(unsigned short,const __gmp_expr &)' : could not deduce
template argument for 'const __gmp_expr &' from
'flint::fmpzxx' fvkey.cpp 135 Error C2784:
'__gmp_expr,__gmp_binary_multiplies>>
operator *(signed char,const __gmp_expr &)' : could not deduce
template argument for 'const __gmp_expr &' from 'flint::fmpzxx'
fvkey.cpp 115
Error C2784: '__gmp_expr,__gmp_binary_minus>> operator -(long
double,const __gmp_expr &)' : could not deduce template argument
for 'const __gmp_expr &' from 'const flint::fmpzxx'
'flint::fmpzxx' fvkey.cpp 116
Error C2784:
'__gmp_expr,mpir_ui,__gmp_binary_multiplies>>
operator *(const __gmp_expr &,unsigned int)' : could not deduce
template argument for 'const __gmp_expr &' from
'int' 'flint::fmpzxx' fvkey.cpp 115
Error C2678: binary '<<' : no operator found which takes a left-hand
operand of type 'flint::fmpzxx_expression' (or there
is no acceptable conversion) fvkey.cpp 50
I've tried to solve it couple of weeks but still unsuccessfully. Whether it is caused by the "fmpz-conversions.h" from FLINT?
Please help me to figure out what I've done incorrectly. I've uploaded my visual project to http://1drv.ms/1LFpCI4.

ad hoc scanner just wont work

So far i have this code that is suppose to be an ad hoc scanner, im not sure where exactly the problem is because i get a very odd error in the output.txt file. it all starts when the program hits the left parenthesis, is there somthing wrong with my checkforoperators function? i have looked but have found little and have even asked others, but no reall luck as to what the problem is.
the input file contains this
read A1
read A2
sum:=(A1-33)+A2*5.5
write sum
write (A1+A2)/2
and the output file is SUPPOSE to look like this
read
A1
read
A2
Sum
:=
(
A1
-
33
)
+
A2
*
5.5
write
sum
write
(
A1
+
A2
)
/
2
heres the main file
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
// This program is an ad-hoc scanner.
// It will recognize tokens and seperate them.
// this language will NOT DISTINGUISH between uppercase or lowercase.
void stripSpacing(string &);
void checkForCommands();
void checkForLetters();
void checkForOperators();
void checkForAssignment();
void checkForDecimal();
void checkForDigit();
int x1 = 0;
int x2 = 0;
int vars[10];
// Only for demonstration purposes, we could use a dynamic array for larger purposes.
string holder;
// used to hold the current string before processing.
fstream handling;
// file handling from other libraries.
fstream output;
char temp1[1];
char temp2[1];
int x = 0;
int xtemp = 0;
int main()
{
output.open("output.txt");
handling.open("input.txt");
if (handling.is_open())
{
while (!handling.eof())
{
dcom:
getline (handling,holder);
if(holder[x] == '/' && holder[x+1] == '/')
{
cout << "This line has only comments.... REMOVED :)" << endl;
//do nothing :)
goto dcom;
}
cout << endl;
stripSpacing(holder);
cout << "The line is this long after removing spaces: " << holder.length() << endl;
cout << "The line contains: " << holder << endl;
cout << endl;
while(holder.length() != x)
{
// let's check for commands, such as read write or sum.
checkForOperators();
checkForAssignment();
checkForDecimal();
checkForDigit();
checkForCommands();
checkForLetters();
}
output << "\n";
x=0;
}
handling.close();
output.close();
return 0;
}
}
void stripSpacing(string &str)
{
for (int i=0; i<str.length(); i++)
if (str[i]==' ')
{
str.erase(i,1);
i--;
}
}
void checkForOperators()
{
if(holder[x] == '(' || holder[x] == ')'|| holder[x] == '+' || holder[x] == '-' || holder[x] == '*' ||holder[x] == '/')
{
output << holder[x] + "\n";
x++;
}
cout << "checkForOpertors" << endl;
}
void checkForCommands()
{
xtemp = x;
if(holder[x] == 'w')
{
x++;
if(holder[x] == 'r')
{
x++;
if(holder[x] == 'i')
{
x++;
if(holder[x] == 't')
{
x++;
if(holder[x] == 'e')
{
x++;
output << "write\n"; goto stop;
}else{x=xtemp; goto stop;}
}else{x=xtemp; goto stop;}
}else{x=xtemp; goto stop;}
}else{x=xtemp; goto stop;}
}
if(holder[x] == 'r')
{
x++;
if(holder[x] == 'e')
{
x++;
if(holder[x] == 'a')
{
x++;
if(holder[x] == 'd')
{
x++;
output << "read\n"; goto stop;
}else{x=xtemp; goto stop;}
}else{x=xtemp; goto stop;}
}else{x=xtemp; goto stop;}
}
if(holder[x] == 's')
{
x++;
if(holder[x] == 'u')
{
x++;
if(holder[x] == 'm')
{
x++;
output << "sum\n"; goto stop;
}else{x=xtemp; goto stop;}
}else{x=xtemp; goto stop;}
}
stop:
cout << "checkForCommand" << endl;
}
void checkForLetters()
{
if(isalpha(holder[x]))
{
output << holder[x];
x++;
}
cout << "checkForLetters" << endl;
}
void checkForAssignment()
{
if(holder[x] == ':')
{
x++;
if(holder[x] == '=')
{
output << ":=\n";
x++;
}
else
{
cout << "ERROR!!! NO : BEFORE =" << endl;
}
}
cout << "checkForAssign" << endl;
}
void checkForDecimal()
{
if(holder[x] == '.')
{
x++;
if(isdigit(holder[x]))
{
output << '.';
x--;
}
}
cout << "checkForDeci" << endl;
}
void checkForDigit()
{
if(isdigit(holder[x]))
{
output << holder[x];
x++;
}
cout << "checkForDig" << endl;
}