Browse Source

Add new version

Jean Fromentin 1 year ago
parent
commit
4ea4b7932b
100 changed files with 2038 additions and 18 deletions
  1. 177 0
      Wilf.ipynb
  2. 40 18
      c++/Makefile
  3. 54 0
      c++/dist/client.cpp
  4. 46 0
      c++/dist/client.hpp
  5. BIN
      c++/dist/client.o
  6. 28 0
      c++/dist/interface.cpp
  7. 15 0
      c++/dist/interface.hpp
  8. BIN
      c++/dist/interface.o
  9. 125 0
      c++/dist/message.cpp
  10. 89 0
      c++/dist/message.hpp
  11. BIN
      c++/dist/message.o
  12. 221 0
      c++/dist/server.cpp
  13. 83 0
      c++/dist/server.hpp
  14. BIN
      c++/dist/server.o
  15. 154 0
      c++/dist/task.hpp
  16. 37 0
      c++/dist/worker.cpp
  17. 20 0
      c++/dist/worker.hpp
  18. BIN
      c++/dist/worker.o
  19. 26 0
      c++/old/Makefile
  20. 0 0
      c++/old/semigroup.cpp
  21. 0 0
      c++/old/semigroup.hpp
  22. 0 0
      c++/old/stack.hpp
  23. 0 0
      c++/old/treewalk.cpp
  24. 0 0
      c++/old/treewalk.hpp
  25. BIN
      c++/semigroup.o
  26. 15 0
      c++/src/config.hpp
  27. 25 0
      c++/src/gtask.cpp
  28. 19 0
      c++/src/gtask.hpp
  29. BIN
      c++/src/gtask.o
  30. 45 0
      c++/src/main-alone.cpp
  31. 39 0
      c++/src/main-interface.cpp
  32. 91 0
      c++/src/main-server.cpp
  33. 41 0
      c++/src/main-worker.cpp
  34. 70 0
      c++/src/main.cpp
  35. 3 0
      c++/src/results.cpp
  36. 115 0
      c++/src/semigroup.cpp
  37. 239 0
      c++/src/semigroup.hpp
  38. BIN
      c++/src/semigroup.o
  39. 41 0
      c++/src/stack.hpp
  40. 133 0
      c++/src/treewalk.cpp
  41. 23 0
      c++/src/treewalk.hpp
  42. BIN
      c++/src/treewalk.o
  43. 24 0
      c++/src/work.hpp
  44. BIN
      c++/treewalk.o
  45. BIN
      c++/vgcore.2379
  46. BIN
      c++/wilf-alone
  47. BIN
      c++/wilf-interface
  48. BIN
      c++/wilf-server
  49. BIN
      c++/wilf-worker
  50. BIN
      old/tasks/task_10_0
  51. BIN
      old/tasks/task_10_1
  52. BIN
      old/tasks/task_10_10
  53. BIN
      old/tasks/task_10_11
  54. BIN
      old/tasks/task_10_12
  55. BIN
      old/tasks/task_10_13
  56. BIN
      old/tasks/task_10_14
  57. BIN
      old/tasks/task_10_15
  58. BIN
      old/tasks/task_10_16
  59. BIN
      old/tasks/task_10_17
  60. BIN
      old/tasks/task_10_18
  61. BIN
      old/tasks/task_10_19
  62. BIN
      old/tasks/task_10_2
  63. BIN
      old/tasks/task_10_20
  64. BIN
      old/tasks/task_10_21
  65. BIN
      old/tasks/task_10_22
  66. BIN
      old/tasks/task_10_23
  67. BIN
      old/tasks/task_10_24
  68. BIN
      old/tasks/task_10_25
  69. BIN
      old/tasks/task_10_26
  70. BIN
      old/tasks/task_10_27
  71. BIN
      old/tasks/task_10_28
  72. BIN
      old/tasks/task_10_29
  73. BIN
      old/tasks/task_10_3
  74. BIN
      old/tasks/task_10_30
  75. BIN
      old/tasks/task_10_31
  76. BIN
      old/tasks/task_10_32
  77. BIN
      old/tasks/task_10_33
  78. BIN
      old/tasks/task_10_34
  79. BIN
      old/tasks/task_10_35
  80. BIN
      old/tasks/task_10_36
  81. BIN
      old/tasks/task_10_37
  82. BIN
      old/tasks/task_10_38
  83. BIN
      old/tasks/task_10_39
  84. BIN
      old/tasks/task_10_4
  85. BIN
      old/tasks/task_10_40
  86. BIN
      old/tasks/task_10_41
  87. BIN
      old/tasks/task_10_42
  88. BIN
      old/tasks/task_10_43
  89. BIN
      old/tasks/task_10_44
  90. BIN
      old/tasks/task_10_45
  91. BIN
      old/tasks/task_10_46
  92. BIN
      old/tasks/task_10_47
  93. BIN
      old/tasks/task_10_48
  94. BIN
      old/tasks/task_10_49
  95. BIN
      old/tasks/task_10_5
  96. BIN
      old/tasks/task_10_50
  97. BIN
      old/tasks/task_10_51
  98. BIN
      old/tasks/task_10_52
  99. BIN
      old/tasks/task_10_53
  100. 0 0
      old/tasks/task_10_54

+ 177 - 0
Wilf.ipynb

@@ -0,0 +1,177 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "39290436",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "n_40=774614285"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "08be6db1",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "s_40=123536994"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "cdb9c339",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "0.159481946553568"
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s_40/n_40*1.0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "dbb20f7b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "s_39=76913321"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "035141ec",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1.60618462957802"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s_40/s_39*1.0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "44b6704f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "n_39=474851445"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "3e936097",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1.63127709340760"
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "n_40/n_39*1.0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "249f2bfa",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "n30=5646773"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "17555fd0",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "n29=3437839"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "d889e146",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1.64253561612397"
+      ]
+     },
+     "execution_count": 11,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "n30/n29*1.0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "0bbf8d67",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "SageMath 9.8",
+   "language": "sage",
+   "name": "sagemath"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.3"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}

+ 40 - 18
c++/Makefile

@@ -1,26 +1,48 @@
-# CILK_ROOT must contains the GCC/Cilk root directory
-OS     	    = $(shell uname)
-MAX_GENUS   = $(shell cat ../genus)
-CPPFLAGS    = -DMAX_GENUS=$(MAX_GENUS) #-DNDEBUG
-CXXFLAGS    = -std=c++11 -g -Wall -O3 # -fsanitize=thread # -Winline
-CXX         = g++
-TARGET_ARCH = -march=corei7 -mtune=corei7
-TARGET 	    = ../wilf
+EXE_W		= wilf-worker
+EXE_S 		= wilf-server
+EXE_I 		= wilf-interface
+EXE_A   	= wilf-alone
+CPP 		= g++  -g
+CFLAGS		= --std=c++11 -march=corei7 -O3 -DNDEBUG
 
+all: $(EXE_S) $(EXE_W) $(EXE_I) $(EXE_A)
 
+dist/message.o:dist/message.cpp dist/message.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
 
-# Pour compiler avec une valeur différente: make MAX_GENUS=35
-#DEFAULT_MAX_GENUS=40
-#MAX_GENUS=$(DEFAULT_MAX_GENUS)
+dist/client.o:dist/client.cpp dist/client.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
 
-all: $(TARGET)
+dist/server.o:dist/server.cpp dist/server.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
 
-semigroup.o: semigroup.cpp semigroup.hpp ../genus
-treewalk.o: treewalk.cpp treewalk.hpp semigroup.hpp stack.hpp ../genus
-../wilf: treewalk.o semigroup.o
-	$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
+dist/interface.o:dist/interface.cpp dist/interface.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
 
-clean:
-	rm -rf $(TARGET) *.o *~ 
+dist/worker.o:dist/worker.cpp dist/worker.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
+
+src/gtask.o:src/gtask.cpp src/gtask.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
+
+src/semigroup.o:src/semigroup.cpp src/semigroup.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
+
+src/treewalk.o:src/treewalk.cpp src/treewalk.hpp
+	$(CPP) $(CFLAGS) -c $< -o $@
+
+$(EXE_W):dist/message.o dist/client.o dist/worker.o src/semigroup.o src/treewalk.o src/main-worker.cpp
+	$(CPP) $(CFLAGS) $^ -o $@ $(LIBS)
 
+$(EXE_S):dist/message.o dist/server.o src/gtask.o src/semigroup.o src/treewalk.o src/main-server.cpp
+	$(CPP) $(CFLAGS) $^ -o $@ $(LIBS)
 
+$(EXE_I):dist/message.o dist/client.o dist/interface.o src/main-interface.cpp
+	$(CPP) $(CFLAGS) $^ -o $@ $(LIBS)
+
+$(EXE_A):src/semigroup.o src/treewalk.o src/main-alone.cpp
+	$(CPP) $(CFLAGS) $^ -o $@ $(LIBS)
+
+
+clean:
+	$(RM) -rf $(EXE_W) $(EXE_S) $(EXE_I) $(EXE_A)  data/* dist/*.o dist/*~ src/*.o src/*~

+ 54 - 0
c++/dist/client.cpp

@@ -0,0 +1,54 @@
+#include "client.hpp"
+
+Client::Client(string server_ip,int server_port){
+  socket_fd=socket(AF_INET, SOCK_STREAM, 0);
+  if(socket_fd<0){
+    cerr<<"[Error] I can't open socket"<<endl;
+    exit(-1);
+  }
+  sockaddr_in serv_addr;
+  bzero((char *) &serv_addr, sizeof(serv_addr));
+  serv_addr.sin_family = AF_INET;
+  serv_addr.sin_addr.s_addr = inet_addr(server_ip.c_str());
+  serv_addr.sin_port = htons(server_port);
+  if(connect(socket_fd,(struct sockaddr *) &serv_addr,sizeof(serv_addr))<0){
+    cerr<<"[Error] I can't connect socket"<<endl;
+    cout<<errno<<endl;
+    exit(-1);
+  }
+  has_message=false;
+}
+
+void Client::listen(){
+  char buffer;
+  int l=recv(socket_fd,&buffer,1,MSG_PEEK);
+  if(l>0){
+    get_message();
+  }
+  if(l==0){
+    cerr<<"[Error] Server was done"<<endl;
+    exit(-1);
+  }
+}
+
+void
+Client::get_message(){
+  char buffer;
+  message.clear();
+  do{
+    recv(socket_fd,&buffer,1,0);
+  }while(message.add(buffer));
+  has_message=true;
+}
+
+void
+Client::send_string(string str){
+  size_t offset=0;
+  Message msg;
+  while(offset<str.size()){
+    size_t len=min((size_t)(MAX_MSG_SIZE-3),str.size()-offset);
+    msg.set_string(str.substr(offset,len));
+    send_message(msg);
+    offset+=len;
+  }
+}

+ 46 - 0
c++/dist/client.hpp

@@ -0,0 +1,46 @@
+#ifndef DIST_CLIENT_HPP
+#define DIST_CLIENT_HPP
+#include <iostream>
+#include <sys/socket.h>
+#include <sys/fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <strings.h>
+#include <unistd.h>
+#include "message.hpp"
+
+using namespace std;
+
+class Client{
+protected:
+   void send_message(Message& msg);
+  bool has_message;
+  Message message;
+ public:
+  char Buffer[MAX_MSG_SIZE];
+  int socket_fd;
+  Client(string server_ip,int server_port);
+  ~Client();
+  void send_code(char l);
+  void send_string(string str);
+  void listen();
+  void get_message();
+};
+
+inline
+Client::~Client(){
+  close(socket_fd);
+}
+
+inline void
+Client::send_message(Message& msg){
+  send(socket_fd,msg.buffer,msg.size,0);
+}
+
+inline void
+Client::send_code(char c){
+  Message msg;
+  msg.set_code(c);
+  send_message(msg);
+}
+#endif

BIN
c++/dist/client.o


+ 28 - 0
c++/dist/interface.cpp

@@ -0,0 +1,28 @@
+#include "interface.hpp"
+
+void
+Interface::get_informations(){
+  cout<<endl<<"========= Informations ========="<<endl;
+  while(true){
+    listen();
+    if(has_message){
+      has_message=false;
+      switch(message.get_type()){
+      case STRING:
+	cout<<message.get_string()<<endl;
+	break;
+      case CODE:
+	if(message.get_code()=='E') return;
+	cerr<<"[Error] Receive unexpected code "<<message.get_code()<<endl;
+	return;
+	break;
+      default:
+	cerr<<"[Error] Receive unexpected message"<<endl;
+	return;
+	break;
+      }
+    }
+    else usleep(10000);
+  }
+  cout<<"================================"<<endl;
+}

+ 15 - 0
c++/dist/interface.hpp

@@ -0,0 +1,15 @@
+#ifndef INTERFACE_HPP
+#define INTERFACE_HPP
+
+#include "client.hpp"
+
+class Interface:public Client{
+public:
+  Interface(string ip,int port);
+  void get_informations();
+};
+
+inline
+Interface::Interface(string ip,int port):Client(ip,port){
+}
+#endif

BIN
c++/dist/interface.o


+ 125 - 0
c++/dist/message.cpp

@@ -0,0 +1,125 @@
+#include "message.hpp"
+
+void
+Message::set_string(string s){
+  size=s.size()+3;
+  assert(size<=MAX_MSG_SIZE);
+  buffer[0]=STRING;
+  uint16_t u=s.size();
+  memcpy(&buffer[1],(char*)&u,2);
+  memcpy(&buffer[3],s.c_str(),s.size());
+}
+
+void
+Message::set_integer(Integer i){
+  size=1+sizeof(Integer);
+  buffer[0]=INTEGER;
+  memcpy(&buffer[1],(char*)&i,sizeof(Integer));
+}
+
+void
+Message::set_data(const char* data_buffer,size_t data_size){
+  size=1+sizeof(size_t)+data_size;
+  buffer[0]=DATA;
+  size_t offset=1;
+  memcpy(&buffer[1],&data_size,sizeof(size_t));
+  memcpy(&buffer[1+sizeof(size_t)],data_buffer,data_size);
+}
+
+bool
+Message::add(char l){
+  if(csize==0){
+    csize=1;
+    buffer[0]=l;
+    switch(l){
+    case CODE:
+      size=2;
+      break;
+    case INTEGER:
+      size=1+sizeof(Integer);
+      break;
+    case STRING:
+    case DATA:
+      break;
+    default:
+      cerr<<"[Error] Message type unkown ("<<l<<')'<<endl;
+      return false;
+      break;
+    }
+    return true;
+  }
+  switch(buffer[0]){
+  case CODE:
+    return add_to_code(l);
+    break;
+  case STRING:
+    return add_to_string(l);
+    break;
+  case INTEGER:
+    return add_to_integer(l);
+    break;
+  case DATA:
+    return add_to_data(l);
+    break;
+  default:
+    cerr<<"[Error] Message type unkown"<<endl;
+    return false;
+    break;
+  }
+  return false;  
+}
+
+bool
+Message::add_to_code(char l){
+  csize=2;
+  buffer[1]=l;
+  return false;
+}
+
+bool
+Message::add_to_string(char l){
+  if(csize==1){
+    buffer[csize++]=l;
+    return true;
+  }
+  if(csize==2){
+    buffer[csize++]=l;
+    uint16_t s;
+    memcpy(&s,&buffer[1],2);
+    size=s+3;
+    return true;
+  }
+  buffer[csize++]=l;
+  return csize<size; 
+}
+
+bool
+Message::add_to_integer(char l){
+  buffer[csize++]=l;
+  return csize<size;
+}
+
+bool
+Message::add_to_data(char l){
+  if(csize==1+sizeof(size_t)){
+    size_t s;
+    memcpy(&s,&buffer[1],sizeof(size_t));
+    size=csize+s;
+  }
+  buffer[csize++]=l;
+  return csize<max(2+sizeof(size_t),size);
+}
+
+size_t
+Message::get_data_size(){
+  assert(buffer[0]==DATA);
+  size_t data_size;
+  memcpy(&data_size,&buffer[1],sizeof(size_t));
+  return data_size;  
+}
+
+char*
+Message::get_data_buffer(){
+  assert(buffer[0]==DATA);
+  return &buffer[1+sizeof(size_t)];  
+}

+ 89 - 0
c++/dist/message.hpp

@@ -0,0 +1,89 @@
+#ifndef DIST_MESSAGE_HPP
+#define DIST_MESSAGE_HPP
+
+#include <iostream>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include "task.hpp"
+
+#define MAX_MSG_SIZE 1024
+
+enum MessageType : char{UNKOWN,CODE,STRING,INTEGER,DATA};
+
+using Integer=int64_t;
+
+
+using namespace std;
+
+struct Data{
+  char* buffer;
+  size_t size;
+};
+
+class Message{
+private:
+  size_t csize;
+public:
+  char buffer[MAX_MSG_SIZE];
+  size_t size;
+  void set_code(char c);
+  void set_string(string s);
+  void set_integer(Integer i);
+  void set_data(const char* buffer,size_t s);
+  void clear();
+  bool add(char l);
+  bool add_to_code(char l);
+  bool add_to_string(char l);
+  bool add_to_integer(char l);
+  bool add_to_data(char l);
+  MessageType get_type();
+  char get_code();
+  string get_string();
+  Integer get_integer();
+  size_t get_data_size();
+  char* get_data_buffer();
+};
+
+inline void
+Message::set_code(char c){
+  size=2;
+  buffer[0]=CODE;
+  buffer[1]=c;
+}
+
+inline void
+Message::clear(){
+  csize=0;
+  size=0;
+}
+
+inline MessageType
+Message::get_type(){
+  return (MessageType)buffer[0];
+}
+
+inline char
+Message::get_code(){
+  assert(buffer[0]==CODE);
+  return buffer[1];
+}
+
+inline string
+Message::get_string(){
+  assert(buffer[0]==STRING);
+  size_t s=size-3;
+  return string(&buffer[3],s);
+}
+
+inline Integer
+Message::get_integer(){
+  assert(buffer[0]==INTEGER);
+  Integer i;
+  memcpy(&i,&buffer[1],sizeof(Integer));
+  return i;
+}
+
+
+
+#endif

BIN
c++/dist/message.o


+ 221 - 0
c++/dist/server.cpp

@@ -0,0 +1,221 @@
+#include "server.hpp"
+
+Server::Server(size_t _max_clients,int port){
+  //--------------------------
+  // Create connection socket
+  //--------------------------
+  connection_socket=socket(AF_INET, SOCK_STREAM, 0);
+  if(connection_socket<0){
+    cerr<<"[Error] Can not open socket"<<endl;
+    exit(-1);
+  }
+  //Set socket for nonblocking
+  if(fcntl(connection_socket, F_SETFL, O_NONBLOCK)<0){
+    cerr<<"[Error] Can not set socket for unblocking"<<endl;
+    exit(-1);
+  }
+  sockaddr_in serv_addr;
+  bzero((char *) &serv_addr, sizeof(serv_addr));
+  serv_addr.sin_family = AF_INET;
+  serv_addr.sin_addr.s_addr = INADDR_ANY;
+  serv_addr.sin_port = htons(port);
+  if(bind(connection_socket,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0){
+    cerr<<"[Error] Can not bind socket"<<endl;
+    exit(-1);
+  }
+  listen(connection_socket,5);
+  //---------
+  // Clients
+  //---------
+  int pid=getpid();
+ 
+  cout<<"Pid is "<<pid<<endl;
+  max_clients=_max_clients;
+  struct rlimit limit;
+  getrlimit(RLIMIT_NOFILE,&limit);
+  limit.rlim_cur=max_clients;
+  int res=prlimit(0,RLIMIT_NOFILE,&limit,NULL);
+  cout<<"Maximal number of clients = "<<max_clients<<endl;
+  nb_clients=0;
+  clients=new ClientInformation[max_clients];
+  //---------
+  // Tasks
+  //---------
+  tasks=nullptr;
+  nb_tasks=0;
+  nb_finished_tasks=0;
+  nb_workers=0;
+
+  treat=nullptr;
+}
+
+void Server::set_tasks(Task* _tasks,size_t _nb_tasks){
+  tasks=_tasks;
+  nb_tasks=_nb_tasks;
+  nb_finished_tasks=0;
+}
+
+Server::~Server(){
+  cout<<" Close server."<<endl;
+  for(size_t c=0;c<nb_clients;++c){
+    close(clients[c].socket);
+  }
+  delete[] clients;
+  close(connection_socket);
+}
+
+void
+Server::listen_for_new_clients(){
+  if(nb_clients<max_clients){
+    int socket=accept(connection_socket, NULL, NULL);
+    if(socket>=0){
+      //Set socket for nonblocking
+      fcntl(socket, F_SETFL, O_NONBLOCK);
+      clients[nb_clients].socket=socket;
+      clients[nb_clients].has_message=false;
+      clients[nb_clients].is_worker=false;
+      clients[nb_clients].current_task=nullptr;
+      ++nb_clients;
+    }
+  }
+}
+
+void Server::listen_clients(){
+  char buffer;
+  for(size_t c=0;c<nb_clients;++c){
+    int l=recv(clients[c].socket,&buffer,1,MSG_PEEK);
+    if(l>0){
+      if(not clients[c].has_message){
+	get_message(c);
+      }
+    }
+    if(l==0) remove_client(c);
+  }
+}
+
+void Server::remove_client(size_t c){
+   ClientInformation& client=clients[c];
+  if(client.is_worker){
+    Task* task=client.current_task;
+    if(task!=nullptr){
+      if(task->get_statut()!=Task::Done){
+	task->set_statut(Task::Unaffected);
+      }
+    }
+    --nb_workers;
+  }
+  --nb_clients;
+  close(clients[c].socket);
+  for(size_t i=c;i<nb_clients;++i){
+    clients[i]=clients[i+1];
+  }
+}
+
+void
+Server::get_message(size_t c){
+  //cout<<"Receive message from "<<c<<endl;
+  char buffer;
+  Message& message=clients[c].message;
+  message.clear();
+  do{
+    recv(clients[c].socket,&buffer,1,0);
+  }while(message.add(buffer));
+  clients[c].has_message=true;
+}
+
+void
+Server::send_string(size_t c,string str){
+  size_t offset=0;
+  Message msg;
+  while(offset<str.size()){
+    size_t len=min((size_t)(MAX_MSG_SIZE-3),str.size()-offset);
+    msg.set_string(str.substr(offset,len));
+    send_message(c,msg);
+    offset+=len;
+  }
+}
+
+void
+Server::treat_message(size_t c){
+  //cout<<"Treat message from "<<c<<endl;
+  Message& message=clients[c].message;
+  switch(message.get_type()){
+  case CODE:
+    switch(message.get_code()){
+    case 'I':
+      send_informations(c);
+      break;
+    case 'K':
+      for(size_t c=0;c<nb_clients;++c){
+	send_code(c,'K');
+      }
+      exit(0);
+      break;
+    case 'W':
+      clients[c].is_worker=true;
+      clients[c].current_task=nullptr;
+      ++nb_workers;
+      break;
+    default:
+      cerr<<"[Error] Receive unexpected code "<<message.get_code()<<" from client "<<c<<endl;
+      break;
+    };
+    break;
+  case DATA:
+    //cout<<" DATA"<<endl;
+    get_task(c);
+    clients[c].current_task=nullptr;
+    break;
+  default:
+    cerr<<"[Error] Receive unexpected message from client "<<c<<" with type "<<message.get_type()<<endl;
+    break;
+  }
+  clients[c].has_message=false;
+}
+
+void
+Server::send_informations(size_t c){
+  send_string(c,"Tasks : "+to_string(nb_tasks));
+  send_string(c,"Tasks done : "+to_string(nb_finished_tasks));
+  send_string(c,"Clients : "+to_string(nb_clients));
+  send_string(c,"Workers : "+to_string(nb_workers));
+  send_code(c,'E');
+}
+
+void
+Server::affect_tasks(){
+  for(size_t c=0;c<nb_clients;++c){
+    if(clients[c].is_worker and clients[c].current_task==nullptr){
+      affect_task(c);
+    }
+  }								    
+}
+
+void
+Server::affect_task(size_t c){
+  //Find first unafected task
+  for(size_t i=0;i<nb_tasks;++i){
+    if(tasks[i].get_statut()==Task::Unaffected){
+      //Affect task i
+      clients[c].current_task=&tasks[i];
+      tasks[i].set_statut(Task::Affected);
+      Message msg;
+      msg.set_data(tasks[i].get_input(),tasks[i].get_input_size());
+      send_message(c,msg);
+      return;
+    }
+  }
+}
+
+void
+Server::get_task(size_t c){
+  Task* task=clients[c].current_task;
+  Message& message=clients[c].message;
+  task->set_output(message.get_data_buffer(),message.get_data_size());
+  task->set_statut(Task::Done);
+  ++nb_finished_tasks;
+  if(treat!=nullptr){
+    bool stop=treat(*task);
+    if(stop) nb_finished_tasks=nb_tasks;
+  }
+}

+ 83 - 0
c++/dist/server.hpp

@@ -0,0 +1,83 @@
+#ifndef SERVER_HPP
+#define SERVER_HPP
+#include <iostream>
+#include <sys/socket.h>
+#include <sys/fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <strings.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include "message.hpp"
+#include "task.hpp"
+
+using namespace std;
+
+struct ClientInformation{
+  int socket;
+  bool has_message;
+  Message message;
+  void* data;
+  bool is_worker;
+  Task* current_task;
+};
+
+class Server{
+private:
+  void send_message(size_t c,Message& msg);
+public:
+  bool (*treat)(Task& t);
+  size_t nb_clients;
+  size_t max_clients;
+  size_t nb_workers;
+  Task* tasks;
+  size_t nb_tasks;
+  size_t nb_finished_tasks;
+  ClientInformation* clients;
+  int connection_socket;
+  char Buffer[MAX_MSG_SIZE];
+  Server(size_t max_clients,int port);
+  ~Server();
+  void listen_for_new_clients();
+  void listen_clients();
+  void remove_client(size_t c);
+  void get_message(size_t c);
+  void send_code(size_t c,char code);
+  void send_string(size_t c,string str);
+  void treat_messages();
+  void treat_message(size_t c);
+  void send_informations(size_t c);
+  void affect_task(size_t c);
+  void affect_tasks();
+  void get_task(size_t c);
+  bool has_unfinished_tasks();
+  void set_tasks(Task* tasks,size_t nb_tasks);
+};
+
+inline void
+Server::send_message(size_t c,Message& msg){
+  send(clients[c].socket,msg.buffer,msg.size,0);
+}
+
+inline void
+Server::send_code(size_t c,char code){
+  Message msg;
+  msg.set_code(code);
+  send_message(c,msg);
+}
+
+inline void
+Server::treat_messages(){
+  for(size_t c=0;c<nb_clients;++c){
+    if(clients[c].has_message){
+      treat_message(c);
+    }
+  }			 
+}
+
+inline bool
+Server::has_unfinished_tasks(){
+  return nb_finished_tasks<nb_tasks;
+}
+#endif

BIN
c++/dist/server.o


+ 154 - 0
c++/dist/task.hpp

@@ -0,0 +1,154 @@
+#ifndef TASK_HPP
+#define TASK_HPP
+#include <cassert>
+#include <cstring>
+
+class Task{
+public:
+  struct Data;
+  enum Statut{Undefined,Unaffected,Affected,Done};
+protected:
+  char *input,*output;
+  size_t input_size,output_size;
+  Statut statut;
+public:
+  Task();
+  Task(const Task& task);
+  Task(Task&& task);
+  ~Task();
+  Task& operator=(const Task& task);
+  Task& operator=(Task&& task);
+  Statut get_statut() const;
+  void set_statut(Statut s);
+  const char* get_input() const;
+  const char* get_output() const;
+  size_t get_input_size() const;
+  size_t get_output_size() const;
+  void set_input(char* buffer,size_t s);
+  void set_output(char* buffer,size_t s);
+};
+
+struct Task::Data{
+  char* buffer;
+  size_t size;
+};
+
+inline
+Task::Task(){
+  input=nullptr;
+  output=nullptr;
+  statut=Undefined;
+}
+
+inline
+Task::Task(const Task& task){
+  input_size=task.input_size;
+  output_size=task.output_size;
+  if(task.input!=nullptr){
+    memcpy(input,task.input,input_size);
+  }
+  if(task.output!=nullptr){
+    memcpy(output,task.output,output_size);
+  }
+  statut=task.statut;
+}
+
+inline
+Task::Task(Task&& task){
+  input_size=task.input_size;
+  output_size=task.output_size;
+  input=task.input;
+  output=task.output;
+  task.input=nullptr;
+  task.output=nullptr;
+  statut=task.statut;
+}
+
+inline
+Task::~Task(){
+  if(input!=nullptr) delete[] input;
+  if(output!=nullptr) delete[] output;
+}
+
+inline Task&
+Task::operator=(const Task& task){
+  input_size=task.input_size;
+  output_size=task.output_size;
+  if(input==nullptr) delete[] input;
+  if(output==nullptr) delete[] output;
+  if(task.input!=nullptr){
+    memcpy(input,task.input,input_size);
+  }
+  if(task.output!=nullptr){
+    memcpy(output,task.output,output_size);
+  }
+  statut=task.statut;
+  return *this;
+}
+
+inline
+Task& Task::operator=(Task&& task){
+  input_size=task.input_size;
+  output_size=task.output_size;
+  input=task.input;
+  output=task.output;
+  task.input=nullptr;
+  task.output=nullptr;
+  statut=task.statut;
+  return *this;
+}
+
+inline
+Task::Statut
+Task::get_statut() const{
+  return statut;
+}
+
+inline
+void 
+Task::set_statut(Statut s){
+  statut=s;
+}
+
+inline
+const char*
+Task::get_input() const{
+  return input;
+}
+
+inline
+const char*
+Task::get_output() const{
+  return output;
+}
+
+inline
+size_t
+Task::get_input_size() const{
+  return input_size;
+}
+
+inline
+size_t
+Task::get_output_size() const{
+  return output_size;
+}
+
+inline
+void
+Task::set_input(char* buffer,size_t s){
+  assert(input==nullptr);
+  input_size=s;
+  input=new char[s];
+  memcpy(input,buffer,s);
+}
+
+inline
+void
+Task::set_output(char* buffer,size_t s){
+  assert(output==nullptr);
+  output_size=s;
+  output=new char[s];
+  memcpy(output,buffer,s);
+}
+#endif

+ 37 - 0
c++/dist/worker.cpp

@@ -0,0 +1,37 @@
+#include "worker.hpp"
+
+Task
+Worker::get_task(){
+  Task task;
+  while(true){
+    listen();
+    if(has_message){
+      has_message=false;
+      switch(message.get_type()){
+      case DATA:
+	task.set_input(message.get_data_buffer(),message.get_data_size());
+	return task;
+	break;
+      case CODE:
+	if(message.get_code()=='K'){
+	  cout<<"I quit !"<<endl;
+	  exit(0);
+	}
+	cerr<<"[Error] Receive unexpected code "<<message.get_code()<<endl;
+	exit(-1);
+	break;
+      default:
+	cerr<<"[Error] Receive unexpected message"<<endl;
+	break;
+      }
+    }
+  }
+  return task;
+}
+
+void
+Worker::send_task(Task& task){
+  Message msg;
+  msg.set_data(task.get_output(),task.get_output_size());
+  send_message(msg);
+}

+ 20 - 0
c++/dist/worker.hpp

@@ -0,0 +1,20 @@
+#ifndef WORKER_HPP
+#define WORKER_HPP
+
+#include "client.hpp"
+#include "task.hpp"
+
+class Worker:public Client{
+public:
+  Worker(string ip,int port);
+  Task get_task();
+  void send_task(Task& task);
+};
+
+inline
+Worker::Worker(string ip,int port):Client(ip,port){
+  send_code('W');
+}
+
+
+#endif

BIN
c++/dist/worker.o


+ 26 - 0
c++/old/Makefile

@@ -0,0 +1,26 @@
+# CILK_ROOT must contains the GCC/Cilk root directory
+OS     	    = $(shell uname)
+MAX_GENUS   = $(shell cat ../genus)
+CPPFLAGS    = -DMAX_GENUS=$(MAX_GENUS) #-DNDEBUG
+CXXFLAGS    = -std=c++11 -g -Wall -O3 # -fsanitize=thread # -Winline
+CXX         = g++
+TARGET_ARCH = -march=corei7 -mtune=corei7
+TARGET 	    = ../wilf
+
+
+
+# Pour compiler avec une valeur différente: make MAX_GENUS=35
+#DEFAULT_MAX_GENUS=40
+#MAX_GENUS=$(DEFAULT_MAX_GENUS)
+
+all: $(TARGET)
+
+semigroup.o: semigroup.cpp semigroup.hpp ../genus
+treewalk.o: treewalk.cpp treewalk.hpp semigroup.hpp stack.hpp ../genus
+../wilf: treewalk.o semigroup.o
+	$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+clean:
+	rm -rf $(TARGET) *.o *~ 
+
+

c++/semigroup.cpp → c++/old/semigroup.cpp


c++/semigroup.hpp → c++/old/semigroup.hpp


c++/stack.hpp → c++/old/stack.hpp


c++/treewalk.cpp → c++/old/treewalk.cpp


c++/treewalk.hpp → c++/old/treewalk.hpp


BIN
c++/semigroup.o


+ 15 - 0
c++/src/config.hpp

@@ -0,0 +1,15 @@
+#ifndef CONFIG_HPP
+#define CONFIG_HPP
+#include <cstddef>
+
+using namespace std;
+//#define DATA_DIR string("/home/fromentin/data/") //string("/workdir/lmpa/jfromentin/")
+#define SERVER_IP "127.0.0.1" //"10.1.0.104" //"192.168.1.3" //Orval 04
+#define SERVER_PORT 55556
+#define MAX_MSG_SIZE 1024
+#define MAX_CLIENTS 2048
+#define MAX_WORKERS 2048
+
+#define MAX_GENUS 60
+
+#endif

+ 25 - 0
c++/src/gtask.cpp

@@ -0,0 +1,25 @@
+#include "gtask.hpp"
+
+
+Task*
+generate_gtask(){
+  /* Task* tasks=new Task[split];
+  for(size_t i=0;i<split;++i){
+    GTaskInput input;
+    input.offset=i;
+    tasks[i].set_input((char*)&input,sizeof(input));
+    tasks[i].set_statut(Task::Unaffected);
+  }
+  return tasks;*/
+}
+
+
+
+bool treat(Task& t){
+  return false;
+  /*GTaskOutput& output=*((GTaskOutput*)t.get_output());
+  if(output.number>0){
+    cout<<output.sample<<endl;
+  }
+  return false; //  return output.number>0;*/
+}

+ 19 - 0
c++/src/gtask.hpp

@@ -0,0 +1,19 @@
+#include <set>
+#include <algorithm>
+#include <iostream>
+#include "../dist/task.hpp"
+#include "semigroup.hpp"
+
+using namespace std;
+struct GTaskInput{
+  Semigroup S;
+};
+
+struct GTaskOutput{
+  size_t ng[MAX_GENUS+1];
+};
+
+Task* generate_gtask();
+bool treat(Task& t);
+
+

BIN
c++/src/gtask.o


+ 45 - 0
c++/src/main-alone.cpp

@@ -0,0 +1,45 @@
+#include "config.hpp"
+#include "treewalk.hpp"
+#include "work.hpp"
+#include <iostream>
+
+using namespace std;
+
+/*void test_conjecture(){
+  uint64_t end=(1L<<n);
+  for(size_t u=umin;u<end;++u){
+    Skew s(u);
+    if(s.test_conjecture()){
+      cout<<u<<endl;
+      return;
+    }
+  }
+  }*/
+
+
+int main(int argc,char** argv){
+  Semigroup S;
+  size_t ng[MAX_GENUS+1];
+  init_full_N(S);
+  work_on(S,ng);
+
+  /*for(size_t g=0;g<5;++g){
+    cout<<"==== "<<g<<" ===="<<endl;
+    print_Semigroup_gen(S);
+    cout<<" -- "<<endl;
+    auto it=generator_iter<CHILDREN>(S);
+    ind_t pos=0;
+    it.move_next();
+    Semigroup Snew=remove_generator(S,it.get_gen(),pos++);
+    while(it.move_next()){
+      Semigroup T=remove_generator(S,it.get_gen(),pos++);
+      print_Semigroup_gen(T);
+    }
+    S=Snew;
+  }
+  /*cout<<"**************************"<<endl;
+  cout<<"* Skew Circulant - Alone *"<<endl;
+  cout<<"**************************"<<endl;
+  cout<<" n = "<<n<<endl;
+  test_conjecture();*/
+}

+ 39 - 0
c++/src/main-interface.cpp

@@ -0,0 +1,39 @@
+#include "../dist/interface.hpp"
+#include "config.hpp"
+
+using namespace std;
+int main(int argc,char** argv){
+  cout<<"*****************************"<<endl;
+  cout<<"* Genbraid interface client *"<<endl;
+  cout<<"*****************************"<<endl;
+  Interface interface(SERVER_IP,SERVER_PORT);
+  bool quit=false;
+  while(not quit){
+    cout<<endl;
+    cout<<"---------- Menu ----------"<<endl;
+    cout<<endl;
+    cout<<"   i > get informations"<<endl;
+    cout<<"   k > kill server"<<endl;
+    cout<<"   q > quit"<<endl;
+    cout<<endl;
+    cout<<" choice ? ";
+    char rep;
+    cin>>rep;
+    switch(rep){
+    case 'i':
+      interface.send_code('I');
+      interface.get_informations();
+      break;
+    case 'k':
+      interface.send_code('K');
+      quit=true;
+      break;
+    case 'q':
+      quit=true;
+      break;
+    default:
+      break;     
+    }
+  }
+  return 0;
+}

+ 91 - 0
c++/src/main-server.cpp

@@ -0,0 +1,91 @@
+#include <set>
+#include "config.hpp"
+#include "../dist/server.hpp"
+#include "gtask.hpp"
+#include <algorithm>
+#include <list>
+
+using namespace std;
+
+
+
+int main(int argc,char** argv){
+  // Compute the Forest
+  list<Semigroup> forest;
+  Semigroup O;
+  init_full_N(O);
+  for(size_t g=0;g<MAX_GENUS;++g){
+    auto it=generator_iter<CHILDREN>(O);
+    ind_t pos=0;
+    it.move_next();
+    Semigroup Onext=remove_generator(O,it.get_gen(),pos++);
+    while(it.move_next()){
+      forest.push_back(remove_generator(O,it.get_gen(),pos++));
+    }
+    O=Onext;
+  }
+  // Set tasks
+  size_t nb_tasks=forest.size();
+  Task* tasks=new Task[nb_tasks];
+  size_t ind=0;
+  for(auto it=forest.begin();it!=forest.end();++it){
+    GTaskInput input;
+    input.S=*it;
+    tasks[ind].set_input((char*)&input,sizeof(input));
+    tasks[ind].set_statut(Task::Unaffected);
+    ++ind;
+  }
+
+  int l=1;
+  int sockfd = socket(AF_INET, SOCK_STREAM, 0);
+  if(sockfd<0){
+    cerr<<"[Error] Can not open socket"<<endl;
+    exit(-1);
+  }
+  cout<<"*****************"<<endl;
+  cout<<"* Wilf - Server *"<<endl;
+  cout<<"*****************"<<endl;
+  
+  cout<<endl;
+  cout<<"----------------- [Server info] ----------------"<<endl;
+  Server server(MAX_CLIENTS,SERVER_PORT);
+  server.treat=&treat;
+  cout<<"------------------------------------------------"<<endl;
+  cout<<"Max genus =  "<<MAX_GENUS<<endl;
+  cout<<"Number of tasks : "<<nb_tasks<<endl;
+  server.set_tasks(tasks,nb_tasks);
+  do{
+    server.listen_for_new_clients();
+    server.listen_clients();
+    server.treat_messages();
+    server.affect_tasks();
+    usleep(10000);
+  }while(server.has_unfinished_tasks());
+  size_t number=0;
+  cout<<"***************"<<endl;
+  cout<<"*    Bilan    *"<<endl;
+  cout<<"***************"<<endl;
+  size_t ng[MAX_GENUS+1];
+  for(size_t g=0;g<=MAX_GENUS;++g){
+    ng[g]=1; //Missing left most of each level
+  }  
+  for(size_t i=0;i<nb_tasks;++i){
+    if(tasks[i].get_statut()==Task::Done){
+      GTaskOutput& output=*((GTaskOutput*)tasks[i].get_output());
+      for(size_t g=0;g<=MAX_GENUS;++g){
+	ng[g]+=output.ng[g];
+      }
+      /*  if(output.number!=0){
+	if(number==0){
+	  cout<<"I found "<<output.sample<<endl;
+	}
+	number+=output.number;
+	}*/
+    }
+  }
+  for(size_t g=0;g<=MAX_GENUS;++g){
+    cout<<g<<" -> "<<ng[g]<<endl;
+  }
+  //cout<<"Among a total of "<<number<<endl;
+			       
+}

+ 41 - 0
c++/src/main-worker.cpp

@@ -0,0 +1,41 @@
+#include <set>
+#include <stack>
+#include <fstream>
+#include <cstdlib>
+#include <chrono>
+#include "../dist/worker.hpp"
+#include "gtask.hpp"
+#include "treewalk.hpp"
+#include "work.hpp"
+
+using namespace std;
+/*void test_conjecture(size_t offset,GTaskOutput& output){
+  output.number=0;
+  uint64_t end=(1L<<(n-1));
+  for(size_t u=umin+offset;u<end;u+=split){
+    Skew s(u);
+    if(s.test_conjecture()){
+	cout<<u<<endl;
+      if(output.number==0) output.sample=u;
+      ++output.number;
+    }
+  }
+  }*/
+
+int main(int argc,char** argv){
+  Worker worker(SERVER_IP,SERVER_PORT);
+  while(true){
+    Task task=worker.get_task();
+    const GTaskInput* input=(const GTaskInput*)task.get_input();
+    Semigroup S=input->S;
+    //cout<<"S is "<<endl;
+    //print_Semigroup(S);
+    GTaskOutput output;
+    work_on(S,output.ng);
+    //test_conjecture(offset,output);
+    task.set_output((char*)&output,sizeof(output));
+    //cout<<"Send output"<<endl;
+    worker.send_task(task);
+  }
+}
+ 

+ 70 - 0
c++/src/main.cpp

@@ -0,0 +1,70 @@
+#include <unordered_set>
+#include <cilk/cilk.h>
+#include <cilk/cilk_api.h>
+#include "config.hpp"
+#include "init.hpp"
+#include "work.hpp"
+#include "signature.hpp"
+#include "results.hpp"
+
+using namespace std;
+
+ResultsReducer cilk_result;
+
+template<Gen G> void treat(int l,const Signature<G>& s){
+  size_t n=work(s);
+  int rank=s.rank();
+  //  if(ns!=0) file<<s.csv()<<","<<rank<<","<<ns<<","<<ng<<endl;
+  cilk_result.n(l)+=(rank*n);
+}
+
+template<Gen G> void run(){
+  if(G==Artin){
+    cout<<"*******************"<<endl;
+    cout<<"* Gbraids - Artin *"<<endl;
+    cout<<"*******************"<<endl;
+  }
+  else{
+    cout<<"******************"<<endl;
+    cout<<"* Gbraids - dual *"<<endl;
+    cout<<"******************"<<endl;
+  }
+  cout<<"Number of strands : "<<STRANDS<<endl;
+  cout<<"Combinatorics type : ";
+#ifdef SPHERICAL
+  cout<<"spherical";
+#else
+  cout<<"geodesic";
+#endif
+  cout<<"."<<endl;
+  cout<<"-> Init ";
+  init<G,STRANDS>();
+  cout<<"... done."<<endl;
+  set<Signature<G>> prec,cur;
+  load(1,prec);
+  cout<<" Workers number is "<<__cilkrts_get_nworkers()<<endl;					
+  next_signatures(prec,cur);
+  //cout<<"prec = "<<prec<<endl;
+  //cout<<" cur = "<<cur<<endl;
+  for(char l=2;l<=20;++l){
+    cur.clear();
+    cout<<"------------------------"<<endl;
+    cout<<"Length : "<<(int)l<<endl;
+    next_signatures(prec,cur);
+    fstream file;
+    file.open(DATA_DIR+to_string((int)l)+".csv",ios::out);
+    size_t n_sph=0;
+    size_t n_geo=0;
+    for(auto it=cur.begin();it!=cur.end();++it){
+      cilk_spawn treat(l,*it);
+      //treat(l,*it);
+    }
+    cilk_sync;
+    cout<<"-> "<<cilk_result.n(l)<<endl;
+    swap(cur,prec);
+  }
+}
+
+int main(int argc,char** argv){
+  run<GEN>();
+}

+ 3 - 0
c++/src/results.cpp

@@ -0,0 +1,3 @@
+#include "results.hpp"
+
+ResultsReducer cilk_results;

+ 115 - 0
c++/src/semigroup.cpp

@@ -0,0 +1,115 @@
+#include <iostream>
+#include <cstring>
+#include "semigroup.hpp"
+
+void init_full_N(Semigroup &m){
+  epi8 block ={1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8};
+  for(auto i=0; i<NBLOCKS; i++){
+    m.blocks[i] = block;
+    block = block + 8;
+  }
+  m.genus = 0;
+  m.conductor = 1;
+  m.min = 1;
+  m.left=1;
+  m.left_primitive=0;
+  m.e=1;
+  m.wilf=0;
+}
+
+void init(Semigroup& S,char c,char g,char m,char* d){
+  S.conductor=c;
+  S.genus=g;
+  S.min=m;
+  memcpy((void*)S.decs,(void*)d,(3*MAX_GENUS+1));
+  S.left=0;
+  S.left_primitive=0;
+  S.e=0;
+  for(ind_t i=0;i<S.conductor;++i){
+    if(d[i]>0){
+      ++S.left;
+      if(d[i]==1){
+	++S.e;
+	++S.left_primitive;
+      }
+    }
+  }
+  for(ind_t i=S.conductor;i<S.conductor+S.min;++i){
+    if(d[i]==1){
+      ++S.e;
+    }
+  }
+  S.wilf=S.left*S.e-S.conductor;
+}
+
+void init_ordinary(Semigroup &O,int m){
+  O.decs[0]=1;
+  for(auto i=1;i<2*m;++i){
+    O.decs[i]=i/m;
+  }
+  for(auto i=0;i<SIZE-2*m;++i){
+    O.decs[2*m+i]=2+i/2;
+  }
+			     
+  O.genus = m-1;
+  O.conductor = m;
+  O.min = m;
+  O.left=1;
+  O.left_primitive=0;
+  O.e=m;
+  O.wilf=0;
+}
+
+void print_Semigroup(const Semigroup &m)
+{
+  unsigned int i;
+  std::cout<<"min = "<<m.min<<", cond = "<<m.conductor<<", genus = "<<m.genus<<", decs = ";
+  for (i=0; i<SIZE; i++) std::cout<<((int) m.decs[i])<<' ';
+  std::cout<<std::endl;
+}
+
+void print_Semigroup_gen(const Semigroup &m)
+{
+  unsigned int i;
+  std::cout<<"m = "<<m.min<<", c = "<<m.conductor<<", g = "<<m.genus<<" w = "<<m.wilf<<" ";
+  std::cout<<"< ";
+  for (i=1; i<SIZE; i++){
+    if(m.decs[i]==1){
+      std::cout<<i<<' ';
+    }
+  }
+  std::cout<<'>'<<std::endl;
+}
+
+#include <cmath>
+
+
+void output(const Semigroup& m,fstream& f){
+  int q=ceil(float(m.conductor)/float(m.min));
+  int rho=q*m.min-m.conductor;
+  f<<"c = "<<m.conductor<<", g = "<<m.genus<<", r = "<<rho<<", w = "<<m.wilf<<" : ["<<m.min;
+  for (auto i=m.min+1; i<SIZE; i++){
+    if(m.decs[i]==1){
+      f<<','<<i;
+    }
+  }
+  f<<']'<<endl;
+}
+
+void record(const Semigroup& S,fstream& f){
+  char c,g,m;
+  c=S.conductor;
+  g=S.genus;
+  m=S.min;
+  f.write(&c,1);
+  f.write(&g,1);
+  f.write(&m,1);
+  f.write((char*)(&S.decs),3*MAX_GENUS+1);
+}
+
+void print_epi8(epi8 bl)
+{
+  unsigned int i;
+  for (i=0; i<16; i++) std::cout<<((uint8_t*)&bl)[i]<<' ';
+  std::cout<<std::endl;
+}

+ 239 - 0
c++/src/semigroup.hpp

@@ -0,0 +1,239 @@
+#ifndef SEMIGROUP_HPP
+#define SEMIGROUP_HPP
+
+#include "config.hpp"
+#include <cstdint>
+#include <fstream>
+
+#define SIZE_BOUND (3*(MAX_GENUS-1))
+#define NBLOCKS ((SIZE_BOUND+15) >> 4)
+#define SIZE (NBLOCKS << 4)
+// const uint_fast8_t MAX_GENUS = 40;
+// const uint_fast8_t SIZE_BOUND = (3*(MAX_GENUS-1));
+// const uint_fast8_t NBLOCKS = ((SIZE_BOUND+15) >> 4);
+// const uint_fast8_t SIZE = (NBLOCKS << 4);
+
+#include <x86intrin.h>
+
+typedef uint8_t epi8 __attribute__ ((vector_size (16)));
+typedef uint8_t dec_numbers[SIZE] __attribute__ ((aligned (16)));
+typedef epi8 dec_blocks[NBLOCKS];
+typedef uint_fast64_t ind_t;  // The type used for array indexes
+
+using namespace std;
+
+struct Semigroup
+{
+  union {
+    dec_numbers decs;
+    dec_blocks blocks;
+  };
+  // Dont use char as they have to be promoted to 64 bits to do pointer arithmetic.
+  ind_t conductor, min, genus,left_primitive,left,e,wilf;
+};
+
+void init_full_N(Semigroup &);
+void init(Semigroup&,char,char,char,char*);
+void print_Semigroup(const Semigroup &);
+void print_Semigroup_gen(const Semigroup&);
+void print_epi8(epi8);
+void output(const Semigroup& m,fstream& f);
+void record(const Semigroup& S,fstream& f);
+inline void copy_blocks(      dec_blocks &__restrict__ dst,
+			const dec_blocks &__restrict__ src);
+inline void remove_generator(Semigroup &__restrict__ dst,
+		      const Semigroup &__restrict__ src,
+			     ind_t gen,ind_t pos);
+inline Semigroup remove_generator(const Semigroup &src, ind_t gen,ind_t pos);
+
+
+// typedef enum { ALL, CHILDREN } generator_type;
+class ALL {};
+class CHILDREN {};
+
+// template <generator_type T> class generator_iter
+template <class T> class generator_iter{
+private:
+
+  const Semigroup &m;
+  unsigned int mask;   // movemask_epi8 returns a 32 bits values
+  ind_t iblock, gen, bound;
+
+public:
+
+  generator_iter(const Semigroup &mon);
+  bool move_next();
+  uint8_t count();
+  inline ind_t get_gen() const {return gen; };
+};
+
+
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+////////////////   Implementation part here for inlining   ////////////////
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+/*
+Note: for some reason the code using gcc vector variables is 2-3% faster than
+the code using gcc intrinsic instructions.
+Here are the results of two runs:
+data_mmx =  [9.757, 9.774, 9.757, 9.761, 9.811, 9.819, 9.765, 9.888, 9.774, 9.771]
+data_epi8 = [9.592, 9.535, 9.657, 9.468, 9.460, 9.679, 9.458, 9.461, 9.629, 9.474]
+*/
+
+extern inline epi8 load_unaligned_epi8(const uint8_t *t)
+{ return (epi8) _mm_loadu_si128((__m128i *) (t)); };
+
+extern inline epi8 shuffle_epi8(epi8 b, epi8 sh)    // Require SSE 3
+{ return (epi8) _mm_shuffle_epi8((__m128i) b, (__m128i) sh);}
+
+extern inline int movemask_epi8(epi8 b)
+{ return _mm_movemask_epi8((__m128i) b);};
+
+const epi8 zero   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+const epi8 block1 = zero + 1;
+const uint8_t m1 = 255;
+const epi8 shift16[16] =
+  { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
+    {m1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14},
+    {m1,m1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13},
+    {m1,m1,m1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12},
+    {m1,m1,m1,m1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11},
+    {m1,m1,m1,m1,m1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10},
+    {m1,m1,m1,m1,m1,m1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+    {m1,m1,m1,m1,m1,m1,m1, 0, 1, 2, 3, 4, 5, 6, 7, 8},
+    {m1,m1,m1,m1,m1,m1,m1,m1, 0, 1, 2, 3, 4, 5, 6, 7},
+    {m1,m1,m1,m1,m1,m1,m1,m1,m1, 0, 1, 2, 3, 4, 5, 6},
+    {m1,m1,m1,m1,m1,m1,m1,m1,m1,m1, 0, 1, 2, 3, 4, 5},
+    {m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1, 0, 1, 2, 3, 4},
+    {m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1, 0, 1, 2, 3},
+    {m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1, 0, 1, 2},
+    {m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1, 0, 1},
+    {m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1, 0} };
+const epi8 mask16[16] =
+  { {m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0,m1,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0,m1,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0,m1,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0,m1,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1,m1},
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,m1} };
+
+
+template<> inline generator_iter<ALL>::generator_iter(const Semigroup &mon)
+  : m(mon), bound((mon.conductor+mon.min+15) >> 4){
+  epi8 block;
+  iblock = 0;
+  block = m.blocks[0];
+  mask  = movemask_epi8(block == block1);
+  mask &= 0xFFFE; // 0 is not a generator
+  gen = - 1;
+};
+
+
+template<> inline generator_iter<CHILDREN>::generator_iter(const Semigroup &mon)
+  : m(mon), bound((mon.conductor+mon.min+15) >> 4){
+  epi8 block;
+  iblock = m.conductor >> 4;
+  block = m.blocks[iblock] & mask16[m.conductor & 0xF];
+  mask  = movemask_epi8(block == block1);
+  gen = (iblock << 4) - 1;
+};
+
+template <class T> inline uint8_t generator_iter<T>::count(){
+  uint8_t nbr = _mm_popcnt_u32(mask); // popcnt returns a 8 bits value
+  for (ind_t ib = iblock+1; ib < bound; ib++)
+    nbr += _mm_popcnt_u32(movemask_epi8(m.blocks[ib] == block1));
+  return nbr;
+};
+
+template <class T> inline bool generator_iter<T>::move_next(){
+  while (!mask){
+    iblock++;
+    if (iblock > bound) return false;
+    gen = (iblock << 4) - 1;
+    mask  = movemask_epi8(m.blocks[iblock] == block1);
+  }
+  unsigned char shift = __bsfd (mask) + 1; // Bit Scan Forward
+  gen += shift;
+  mask >>= shift;
+  return true;
+};
+
+
+
+inline __attribute__((always_inline))
+void copy_blocks(dec_blocks &dst, dec_blocks const &src){
+  for (ind_t i=0; i<NBLOCKS; i++) dst[i] = src[i];
+}
+
+
+#include <cassert>
+
+inline __attribute__((always_inline))
+void remove_generator(Semigroup &__restrict__ dst,
+		      const Semigroup &__restrict__ src,
+		      ind_t gen,
+		      ind_t pos){
+  ind_t start_block, decal;
+  epi8 block;
+
+  assert(src.decs[gen] == 1);
+
+  ind_t t=gen+1;
+  dst.conductor = t;
+  dst.genus = src.genus + 1;
+  int delta;
+  if(gen==src.min){
+    dst.min=gen+1;
+    delta=1;
+  }
+  else{
+    dst.min=src.min;
+    delta=(src.decs[gen+src.min]==2)?0:-1;
+  }
+  dst.e=src.e+delta;
+  assert(dst.e==((gen==src.min)?src.e+1:((src.decs[gen+src.min]==2)?src.e:src.e-1)));
+  ind_t k=gen-src.conductor;
+  assert(dst.conductor==src.conductor+k+1);
+  dst.left=src.left+k;
+  dst.left_primitive=src.left_primitive+pos;
+  //dst.wilf=dst.e*dst.left-dst.conductor;//src.wilf+delta*(src.left+k)-k-1;
+  dst.wilf=src.wilf+delta*(src.left+k)+(src.e-1)*k-1;
+  copy_blocks(dst.blocks, src.blocks);
+
+  start_block = gen >> 4;
+  decal = gen & 0xF;
+  // Shift block by decal uchar
+  block = shuffle_epi8(src.blocks[0], shift16[decal]);
+  dst.blocks[start_block] -= ((block != zero) & block1);
+
+
+  for (auto i=start_block+1; i<NBLOCKS; i++){
+      // The following won't work due to some alignment problem (bug in GCC 4.7.1?)
+      // block = *((epi8*)(src.decs + ((i-start_block)<<4) - decal));
+      block = load_unaligned_epi8(src.decs + ((i-start_block)<<4) - decal);
+      dst.blocks[i] -= ((block != zero) & block1);
+    }
+  assert(dst.decs[dst.conductor-1] == 0);
+}
+
+inline Semigroup
+remove_generator(const Semigroup &src, ind_t gen,ind_t pos){
+  Semigroup dst;
+  remove_generator(dst, src, gen,pos);
+  return dst;
+}
+
+#endif

BIN
c++/src/semigroup.o


+ 41 - 0
c++/src/stack.hpp

@@ -0,0 +1,41 @@
+#include "semigroup.hpp"
+#ifndef STACK_HPP
+#define STACK_HPP
+
+#define STACK_SIZE (MAX_GENUS*(MAX_GENUS+1))/2
+
+class Stack{
+public:
+  Semigroup data[STACK_SIZE+1], *stack[STACK_SIZE], *other;
+  size_t stack_size;
+  Stack();
+  Semigroup* pop();
+  Semigroup* pushed();
+  bool is_empty();
+};
+
+
+inline
+Stack::Stack(){
+  for (ind_t i=0; i<STACK_SIZE; i++) stack[i] = &(data[i]);
+  other=&data[STACK_SIZE];
+  stack_size=0;
+}
+
+inline Semigroup*
+Stack::pop(){
+  swap(stack[--stack_size],other);
+  return other;
+}
+
+inline Semigroup*
+Stack::pushed(){
+  return stack[stack_size++];
+};
+
+inline bool
+Stack::is_empty(){
+  return stack_size==0;
+}
+
+#endif

+ 133 - 0
c++/src/treewalk.cpp

@@ -0,0 +1,133 @@
+#include <iostream>
+#include <iomanip>
+#include <chrono>
+#include <cmath>
+#include <cpuid.h>
+#include <fstream>
+#include <csignal>
+#include <unistd.h>
+
+#include "treewalk.hpp"
+
+using namespace std;
+using namespace std::chrono;
+
+
+
+bool stack_correct;
+#define SIGNAL_CHECKPOINT SIGUSR2
+
+
+
+void treat(const Semigroup& m){
+  int q=ceil(float(m.conductor)/float(m.min));
+  unsigned int rho=q*m.min-m.conductor;
+  if(m.wilf<=rho){
+    if((m.wilf<0) or (m.wilf<=rho and m.e>2 and m.left_primitive>1 and q>=4)){
+      //output(m,file_out);
+    }
+  }
+}
+
+
+
+void walk(Stack& stack,size_t* res){
+  Semigroup *current,*son;
+  Semigroup temp;
+  while(not stack.is_empty()){
+    current = stack.pop();
+    size_t g=current->genus;
+    if(true or not cut(*current)){
+      if(g < MAX_GENUS - 1){
+	auto it=generator_iter<CHILDREN>(*current);
+	ind_t pos=0;
+	while (it.move_next()){
+	  remove_generator(temp, *current, it.get_gen(),pos++);
+	  if(is_special(temp)){
+	    son=stack.pushed();
+	    *son=temp;
+	    res[g+1]++;
+	  }
+	  //treat(*son);
+	}
+      }
+      else{
+	auto it = generator_iter<CHILDREN>(*current);
+	ind_t pos=0;
+	while (it.move_next()){
+	  remove_generator(temp, *current, it.get_gen(),pos++);
+	  if(is_special(temp)){
+	    res[g+1]++;
+	  }
+	  //treat(temp);
+	}
+      }
+    }
+  }
+}
+
+
+/*int main(int argc, char **argv){
+  if(argc!=2){
+    cerr<<"Usage : "<<argv[0]<<" tasks/task_file"<<endl;
+    exit(-1);
+  }
+  char* task_filename=argv[1];
+  unsigned int ax, bx, cx, dx;
+  if (!__get_cpuid(0x00000001, &ax, &bx, &cx, &dx)){
+    cerr << "Unable to determine the processor type !" << endl;
+    return EXIT_FAILURE;
+  }
+  if (!(cx & bit_SSSE3)){
+    cerr << "This programm require sse3 instructions set !" << endl;
+    return EXIT_FAILURE;
+  }
+  if (!(cx & bit_POPCNT)){
+    cerr << "This programm require popcount instruction !" << endl;
+    return EXIT_FAILURE;
+  }
+  fstream file_in;
+  file_in.open(task_filename,ios::in|ios::binary);
+  string filename=string("tasks/")+task_filename;
+  filename+="-out";
+  file_out.open(filename,ios::out|ios::trunc);
+  Stack stack;
+  char d[3*MAX_GENUS+1];
+  char c,g,m;
+  size_t n;
+  file_in.read((char*)&n,8);
+  cout<<"Stack size = "<<n<<endl;
+  for(size_t i=0;i<n;++i){
+    file_in.read(&c,1);
+    file_in.read(&g,1);
+    file_in.read(&m,1);
+    file_in.read(d,3*MAX_GENUS+1);
+    Semigroup* S=stack.pushed();
+    init(*S,c,g,m,d);
+    treat(*S);
+  }
+  file_in.close();
+  checkpoint=false;
+  signal(SIGNAL_CHECKPOINT, signal_checkpoint_handler);
+  walk(stack);
+
+  file_out.close();
+  if(checkpoint){
+    cout<<"Stoping exploration due to checkpoint signal reception."<<endl;
+    filename=string("tasks/checkpoint/")+task_filename+string("-checkpoint");
+    fstream file_stack;
+    file_stack.open(filename.c_str(),ios::out|ios::binary);
+    size_t size=stack.stack_size;
+    file_stack.write((char*)(&size),8);
+    cout<<"Checkpoint size : "<<size<<endl;
+    for(size_t i=0;i<size;++i){
+      record(*stack.stack[i],file_stack);
+    }
+    file_stack.close();
+    return 1;
+  }
+  else{
+    return 0;
+  }
+}
+*/

+ 23 - 0
c++/src/treewalk.hpp

@@ -0,0 +1,23 @@
+#ifndef TREEWALK_HPP
+#define TREEWALK_HPP
+#include "semigroup.hpp"
+#include "stack.hpp"
+
+bool cut(const Semigroup& m);
+void treat(const Semigroup& m);
+void walk(Stack& stack,size_t* res);
+void signal_checkpoint_handler(int signum);
+
+inline bool
+cut(const Semigroup& m){
+  if(3*m.left_primitive>=m.min) return true;
+  return false;
+}
+
+inline bool is_special(const Semigroup& S){
+  ind_t c=S.conductor;
+  ind_t m=S.min;
+  ind_t x=c+(m-1)-c%m;
+  return S.decs[x]==1;
+}
+#endif

BIN
c++/src/treewalk.o


+ 24 - 0
c++/src/work.hpp

@@ -0,0 +1,24 @@
+#ifndef WORK_HPP
+#define WORK_HPP
+
+#include <iostream>
+#include "treewalk.hpp"
+
+using namespace std;
+
+bool work_on(Semigroup& S,size_t* res){
+  Stack stack;
+  for(size_t g=0;g<=MAX_GENUS;++g){
+    res[g]=0;
+  }
+  if(is_special(S)){
+    res[S.genus]=1;
+    Semigroup* root=stack.pushed();
+    *root=S;
+    walk(stack,res);
+  }
+  return false;
+}
+
+
+#endif

BIN
c++/treewalk.o


BIN
c++/vgcore.2379


BIN
c++/wilf-alone


BIN
c++/wilf-interface


BIN
c++/wilf-server


BIN
c++/wilf-worker


BIN
old/tasks/task_10_0


BIN
old/tasks/task_10_1


BIN
old/tasks/task_10_10


BIN
old/tasks/task_10_11


BIN
old/tasks/task_10_12


BIN
old/tasks/task_10_13


BIN
old/tasks/task_10_14


BIN
old/tasks/task_10_15


BIN
old/tasks/task_10_16


BIN
old/tasks/task_10_17


BIN
old/tasks/task_10_18


BIN
old/tasks/task_10_19


BIN
old/tasks/task_10_2


BIN
old/tasks/task_10_20


BIN
old/tasks/task_10_21


BIN
old/tasks/task_10_22


BIN
old/tasks/task_10_23


BIN
old/tasks/task_10_24


BIN
old/tasks/task_10_25


BIN
old/tasks/task_10_26


BIN
old/tasks/task_10_27


BIN
old/tasks/task_10_28


BIN
old/tasks/task_10_29


BIN
old/tasks/task_10_3


BIN
old/tasks/task_10_30


BIN
old/tasks/task_10_31


BIN
old/tasks/task_10_32


BIN
old/tasks/task_10_33


BIN
old/tasks/task_10_34


BIN
old/tasks/task_10_35


BIN
old/tasks/task_10_36


BIN
old/tasks/task_10_37


BIN
old/tasks/task_10_38


BIN
old/tasks/task_10_39


BIN
old/tasks/task_10_4


BIN
old/tasks/task_10_40


BIN
old/tasks/task_10_41


BIN
old/tasks/task_10_42


BIN
old/tasks/task_10_43


BIN
old/tasks/task_10_44


BIN
old/tasks/task_10_45


BIN
old/tasks/task_10_46


BIN
old/tasks/task_10_47


BIN
old/tasks/task_10_48


BIN
old/tasks/task_10_49


BIN
old/tasks/task_10_5


BIN
old/tasks/task_10_50


BIN
old/tasks/task_10_51


BIN
old/tasks/task_10_52


BIN
old/tasks/task_10_53


+ 0 - 0
old/tasks/task_10_54


Some files were not shown because too many files changed in this diff