<commit_before>/*
 * Copyright (c) 2016 tildearrow
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 *The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifdef _WIN32
#define FONT "C:\\Windows\\Fonts\\segoeui.ttf"
#elif __APPLE__
#define FONT "/System/Library/Fonts/SFNSDisplay-Regular.otf"
#elif __linux__
#define FONT "/usr/share/fonts/TTF/Ubuntu-R.ttf"
#else
#warning "really? please tell me if you are compiling on this OS"
#endif

#include "includes.h"
#include "font.h"
#include "ui.h"
#include "gfxeditor.h"
SDL_Window* mainWindow;
SDL_Renderer* mainRenderer;
SDL_Event* event;
int mouseX;
int mouseY;
unsigned int mouseB;
unsigned int mouseBold;
SDL_Color color[16];
bool willquit;
uisystem* ui;
gfxeditor* geditor;
font* mainFont;
int curview;
int cureditid, curedittype;
const char* viewname[9]={"Graphics","Audio","Entity Types","Scenes","Functions","ShouldNotAppear","ShouldNotAppear","ShouldNotAppear","ShouldNotAppear"};

struct graphic {
  string name;
  int id;
  int width;
  int height;
  int originX, originY;
  int subgraphics;
  bool background;
  std::vector<unsigned char*> data;
  int colmode;
  unsigned char** colmask;
};

struct audio {
  string name;
  int id;
  int size;
  float* data;
  int finaltype;
};

struct etype {
  string name;
  int id;
  int initialgraphic;
  int initialsubgraphic;
  int parent;
  int category;
  std::vector<string> eventcode;
  string headercode;
};

struct viewport {
  SDL_Rect view, port;
  float viewangle, portangle;
};

struct scene {
  string name;
  int id;
  int width;
  int height;
  bool freeze;
  std::vector<viewport> viewports;
};

struct function {
  string name;
  int id;
  string code;
};

std::vector<graphic> graphics;
std::vector<audio> sounds;
std::vector<etype> etypes;
std::vector<scene> scenes;
std::vector<function> functions;

void doNothing(){
  printf("hello world!\n");
}

void drawScreen() {
  SDL_RenderDrawLine(mainRenderer,0,32,1024,32);
  if (curview<5) {
    SDL_RenderDrawLine(mainRenderer,256,32,256,600);
    SDL_RenderDrawLine(mainRenderer,0,53,256,53);
    mainFont->drawf(128,41,color[0],1,1,"%s List",viewname[curview]);
    switch (curview) {
      case 0:
        for (int i=0; i<graphics.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==0)?(color[1]):(color[0])),0,0,false,graphics[i].name);
        }
        // also draw graphic editor
        geditor->draw();
        break;
      case 1:
        for (int i=0; i<sounds.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==1)?(color[1]):(color[0])),0,0,false,sounds[i].name);
        }
        break;
      case 2:
        for (int i=0; i<etypes.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==2)?(color[1]):(color[0])),0,0,false,etypes[i].name);
        }
        break;
      case 3:
        for (int i=0; i<scenes.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==3)?(color[1]):(color[0])),0,0,false,scenes[i].name);
        }
        break;
      case 4:
        for (int i=0; i<functions.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==4)?(color[1]):(color[0])),0,0,false, functions[i].name);
        }
        break;
    }
  }
}

void goGraphicsView() {
  curview=0;
}

void goAudioView() {
  curview=1;
}

void goETypesView() {
  curview=2;
}

void goScenesView() {
  curview=3;
}

void goFunctionsView() {
  curview=4;
}

void goProjectView() {
  curview=5;
}

void goSettingsView() {
  curview=6;
}

void goHelpView() {
  curview=7;
}

void goAboutView() {
  curview=8;
}

void handleMouse() {
  if ((mouseB&1)>(mouseBold&1)) { // checks for mouse left pressed
    if (mouseX<256 && mouseY>64) {
      cureditid=(mouseY-64)/20;
      curedittype=curview;
      switch (curview) {
        case 0: geditor->setdata(graphics[cureditid].data[0], graphics[cureditid].width, graphics[cureditid].height); break;
      }
    }
  }
}

void makeNewResource() {
  // make new resource
  int formersize;
  switch (curview) {
    case 0:
      formersize=graphics.size();
      graphics.resize(formersize+1);
      graphics[formersize].id=formersize;
      graphics[formersize].name="graphic";
      graphics[formersize].name+=std::to_string(formersize);
      // create pre-defined graphic
      graphics[formersize].subgraphics=1;
      graphics[formersize].width=32;
      graphics[formersize].height=32;
      graphics[formersize].data.resize(1);
      graphics[formersize].data[0]=new unsigned char[4096];
      break;
    case 1:
      formersize=sounds.size();
      sounds.resize(formersize+1);
      sounds[formersize].id=formersize;
      sounds[formersize].name="sound";
      sounds[formersize].name+=std::to_string(formersize);
      break;
    case 2:
      formersize=etypes.size();
      etypes.resize(formersize+1);
      etypes[formersize].id=formersize;
      etypes[formersize].name="type";
      etypes[formersize].name+=std::to_string(formersize);
      break;
    case 3:
      formersize=scenes.size();
      scenes.resize(formersize+1);
      scenes[formersize].id=formersize;
      scenes[formersize].name="scene";
      scenes[formersize].name+=std::to_string(formersize);
      break;
    case 4:
      formersize=functions.size();
      functions.resize(formersize+1);
      functions[formersize].id=formersize;
      functions[formersize].name="func";
      functions[formersize].name+=std::to_string(formersize);
      break;
  }
}

int main() {
  willquit=false;
  // init everything
  SDL_Init(SDL_INIT_VIDEO);
  TTF_Init();
  ui=new uisystem;
  event=new SDL_Event;
  string title;
  title="LowerTriad";
  mainWindow=SDL_CreateWindow(title.c_str(),0,0,1024,600,SDL_WINDOW_RESIZABLE);
  if (!mainWindow) {
    printf("i'm sorry, but window can't be created: %s\n",SDL_GetError());
    return 1;
  }
  mainRenderer=SDL_CreateRenderer(mainWindow,-1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  // initialize UI
  mainFont=new font;
  mainFont->setrenderer(mainRenderer);
  if (!mainFont->load(FONT,14)) {
    printf("can't load font, which means this application is going to crash now...\n");
  }
  ui->setrenderer(mainRenderer);
  color[0].r=192; color[0].g=192; color[0].b=192; color[0].a=255; // main
  color[1].r=255; color[1].g=255; color[1].b=255; color[1].a=255; // alternate
  color[2].r=0;   color[2].g=255; color[2].b=0;   color[2].a=255; // success
  color[3].r=255; color[3].g=255; color[3].b=0;   color[3].a=255; // ongoing
  color[4].r=255; color[4].g=0;   color[4].b=0;   color[4].a=255; // failure
  ui->setfont(mainFont);
  ui->addbutton(0,0,48,22,"Prepare","Prepare CMake project",color[0],color[0],doNothing);
  ui->addbutton(48,0,40,22,"Build","Build game",color[0],color[0],doNothing);
  ui->addbutton(100,0,32,22,"Run","Run compiled game",color[0],color[0],doNothing);
  ui->addbutton(132,0,56,22,"Package","Create package",color[0],color[0],doNothing);

  ui->addbutton(200,0,64,22,"Graphics","",color[0],color[0],goGraphicsView);
  ui->addbutton(264,0,50,22,"Audio","Sound/Music",color[0],color[0],goAudioView);
  ui->addbutton(314,0,80,22,"EntityTypes","",color[0],color[0],goETypesView);
  ui->addbutton(394,0,50,22,"Scenes","",color[0],color[0],goScenesView);
  ui->addbutton(444,0,72,22,"Functions","",color[0],color[0],goFunctionsView);
  ui->addbutton(516,0,60,22,"Project","",color[0],color[0],goProjectView);

  ui->addbutton(1024-160,0,60,22,"Settings","",color[0],color[0],goSettingsView);
  ui->addbutton(1024-100,0,50,22,"Help","",color[0],color[0],goHelpView);
  ui->addbutton(1024-50,0,50,22,"About","",color[0],color[0],goAboutView);

  ui->addbutton(225,32,32,22,"Add","Add a new resource",color[0],color[0],makeNewResource);

  ui->setmouse(&mouseX,&mouseY,&mouseB,&mouseBold);
  // initialize graphic editor
  geditor=new gfxeditor;
  geditor->setfont(mainFont);
  // initialize IDE variables
  cureditid=-1; curedittype=0; curview=0;
  while (1) {
    // check events
    while (SDL_PollEvent(event)) {
      if (event->type==SDL_QUIT) {
        willquit=true;
      }
    }
    SDL_SetRenderDrawColor(mainRenderer,0,0,0,0);
    SDL_RenderClear(mainRenderer);
    SDL_SetRenderDrawColor(mainRenderer,color[0].r,color[0].g,color[0].b,color[0].a);
    mouseBold=mouseB;
    mouseB=SDL_GetMouseState(&mouseX, &mouseY);
    handleMouse();
    drawScreen();
    ui->drawall();
    SDL_RenderPresent(mainRenderer);
    if (willquit) {
      break;
    }
  }
  return 0;
}
<commit_msg>so it is fixed now<commit_after>/*
 * Copyright (c) 2016 tildearrow
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 *The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifdef _WIN32
#define FONT "C:\\Windows\\Fonts\\segoeui.ttf"
#elif __APPLE__
#define FONT "/System/Library/Fonts/SFNSDisplay-Regular.otf"
#elif __linux__
#define FONT "/usr/share/fonts/TTF/Ubuntu-R.ttf"
#else
#warning "really? please tell me if you are compiling on this OS"
#endif

#include "includes.h"
#include "font.h"
#include "ui.h"
#include "gfxeditor.h"
SDL_Window* mainWindow;
SDL_Renderer* mainRenderer;
SDL_Event* event;
int mouseX;
int mouseY;
unsigned int mouseB;
unsigned int mouseBold;
SDL_Color color[16];
bool willquit;
uisystem* ui;
gfxeditor* geditor;
font* mainFont;
int curview;
int cureditid, curedittype;
const char* viewname[9]={"Graphics","Audio","Entity Types","Scenes","Functions","ShouldNotAppear","ShouldNotAppear","ShouldNotAppear","ShouldNotAppear"};

struct graphic {
  string name;
  int id;
  int width;
  int height;
  int originX, originY;
  int subgraphics;
  bool background;
  std::vector<unsigned char*> data;
  int colmode;
  unsigned char** colmask;
};

struct audio {
  string name;
  int id;
  int size;
  float* data;
  int finaltype;
};

struct etype {
  string name;
  int id;
  int initialgraphic;
  int initialsubgraphic;
  int parent;
  int category;
  std::vector<string> eventcode;
  string headercode;
};

struct viewport {
  SDL_Rect view, port;
  float viewangle, portangle;
};

struct scene {
  string name;
  int id;
  int width;
  int height;
  bool freeze;
  std::vector<viewport> viewports;
};

struct function {
  string name;
  int id;
  string code;
};

std::vector<graphic> graphics;
std::vector<audio> sounds;
std::vector<etype> etypes;
std::vector<scene> scenes;
std::vector<function> functions;

void doNothing(){
  printf("hello world!\n");
}

void drawScreen() {
  SDL_RenderDrawLine(mainRenderer,0,32,1024,32);
  if (curview<5) {
    SDL_RenderDrawLine(mainRenderer,256,32,256,600);
    SDL_RenderDrawLine(mainRenderer,0,53,256,53);
    mainFont->drawf(128,41,color[0],1,1,"%s List",viewname[curview]);
    switch (curview) {
      case 0:
        for (int i=0; i<graphics.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==0)?(color[1]):(color[0])),0,0,false,graphics[i].name);
        }
        // also draw graphic editor
        geditor->draw();
        break;
      case 1:
        for (int i=0; i<sounds.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==1)?(color[1]):(color[0])),0,0,false,sounds[i].name);
        }
        break;
      case 2:
        for (int i=0; i<etypes.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==2)?(color[1]):(color[0])),0,0,false,etypes[i].name);
        }
        break;
      case 3:
        for (int i=0; i<scenes.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==3)?(color[1]):(color[0])),0,0,false,scenes[i].name);
        }
        break;
      case 4:
        for (int i=0; i<functions.size(); i++) {
          mainFont->draw(0,64+(i*20),((cureditid==i && curedittype==4)?(color[1]):(color[0])),0,0,false, functions[i].name);
        }
        break;
    }
  }
}

void goGraphicsView() {
  curview=0;
}

void goAudioView() {
  curview=1;
}

void goETypesView() {
  curview=2;
}

void goScenesView() {
  curview=3;
}

void goFunctionsView() {
  curview=4;
}

void goProjectView() {
  curview=5;
}

void goSettingsView() {
  curview=6;
}

void goHelpView() {
  curview=7;
}

void goAboutView() {
  curview=8;
}

void handleMouse() {
  if ((mouseB&1)>(mouseBold&1)) { // checks for mouse left pressed
    if (mouseX<256 && mouseY>64) {
      curedittype=curview;
      switch (curview) {
        case 0:
	  cureditid=(mouseY-64)/20;
	  if (cureditid>=graphics.size()) {
	    cureditid=-1;
	  }
	  if (cureditid!=-1) {
	    geditor->setdata(graphics[cureditid].data[0], graphics[cureditid].width, graphics[cureditid].height);
	  }
	  break;
      }
    }
  }
}

void makeNewResource() {
  // make new resource
  int formersize;
  switch (curview) {
    case 0:
      formersize=graphics.size();
      graphics.resize(formersize+1);
      graphics[formersize].id=formersize;
      graphics[formersize].name="graphic";
      graphics[formersize].name+=std::to_string(formersize);
      // create pre-defined graphic
      graphics[formersize].subgraphics=1;
      graphics[formersize].width=32;
      graphics[formersize].height=32;
      graphics[formersize].data.resize(1);
      graphics[formersize].data[0]=new unsigned char[4096];
      break;
    case 1:
      formersize=sounds.size();
      sounds.resize(formersize+1);
      sounds[formersize].id=formersize;
      sounds[formersize].name="sound";
      sounds[formersize].name+=std::to_string(formersize);
      break;
    case 2:
      formersize=etypes.size();
      etypes.resize(formersize+1);
      etypes[formersize].id=formersize;
      etypes[formersize].name="type";
      etypes[formersize].name+=std::to_string(formersize);
      break;
    case 3:
      formersize=scenes.size();
      scenes.resize(formersize+1);
      scenes[formersize].id=formersize;
      scenes[formersize].name="scene";
      scenes[formersize].name+=std::to_string(formersize);
      break;
    case 4:
      formersize=functions.size();
      functions.resize(formersize+1);
      functions[formersize].id=formersize;
      functions[formersize].name="func";
      functions[formersize].name+=std::to_string(formersize);
      break;
  }
}

int main() {
  willquit=false;
  // init everything
  SDL_Init(SDL_INIT_VIDEO);
  TTF_Init();
  ui=new uisystem;
  event=new SDL_Event;
  string title;
  title="LowerTriad";
  mainWindow=SDL_CreateWindow(title.c_str(),0,0,1024,600,SDL_WINDOW_RESIZABLE);
  if (!mainWindow) {
    printf("i'm sorry, but window can't be created: %s\n",SDL_GetError());
    return 1;
  }
  mainRenderer=SDL_CreateRenderer(mainWindow,-1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  // initialize UI
  mainFont=new font;
  mainFont->setrenderer(mainRenderer);
  if (!mainFont->load(FONT,14)) {
    printf("can't load font, which means this application is going to crash now...\n");
  }
  ui->setrenderer(mainRenderer);
  color[0].r=192; color[0].g=192; color[0].b=192; color[0].a=255; // main
  color[1].r=255; color[1].g=255; color[1].b=255; color[1].a=255; // alternate
  color[2].r=0;   color[2].g=255; color[2].b=0;   color[2].a=255; // success
  color[3].r=255; color[3].g=255; color[3].b=0;   color[3].a=255; // ongoing
  color[4].r=255; color[4].g=0;   color[4].b=0;   color[4].a=255; // failure
  ui->setfont(mainFont);
  ui->addbutton(0,0,48,22,"Prepare","Prepare CMake project",color[0],color[0],doNothing);
  ui->addbutton(48,0,40,22,"Build","Build game",color[0],color[0],doNothing);
  ui->addbutton(100,0,32,22,"Run","Run compiled game",color[0],color[0],doNothing);
  ui->addbutton(132,0,56,22,"Package","Create package",color[0],color[0],doNothing);

  ui->addbutton(200,0,64,22,"Graphics","",color[0],color[0],goGraphicsView);
  ui->addbutton(264,0,50,22,"Audio","Sound/Music",color[0],color[0],goAudioView);
  ui->addbutton(314,0,80,22,"EntityTypes","",color[0],color[0],goETypesView);
  ui->addbutton(394,0,50,22,"Scenes","",color[0],color[0],goScenesView);
  ui->addbutton(444,0,72,22,"Functions","",color[0],color[0],goFunctionsView);
  ui->addbutton(516,0,60,22,"Project","",color[0],color[0],goProjectView);

  ui->addbutton(1024-160,0,60,22,"Settings","",color[0],color[0],goSettingsView);
  ui->addbutton(1024-100,0,50,22,"Help","",color[0],color[0],goHelpView);
  ui->addbutton(1024-50,0,50,22,"About","",color[0],color[0],goAboutView);

  ui->addbutton(225,32,32,22,"Add","Add a new resource",color[0],color[0],makeNewResource);

  ui->setmouse(&mouseX,&mouseY,&mouseB,&mouseBold);
  // initialize graphic editor
  geditor=new gfxeditor;
  geditor->setfont(mainFont);
  // initialize IDE variables
  cureditid=-1; curedittype=0; curview=0;
  while (1) {
    // check events
    while (SDL_PollEvent(event)) {
      if (event->type==SDL_QUIT) {
        willquit=true;
      }
    }
    SDL_SetRenderDrawColor(mainRenderer,0,0,0,0);
    SDL_RenderClear(mainRenderer);
    SDL_SetRenderDrawColor(mainRenderer,color[0].r,color[0].g,color[0].b,color[0].a);
    mouseBold=mouseB;
    mouseB=SDL_GetMouseState(&mouseX, &mouseY);
    handleMouse();
    drawScreen();
    ui->drawall();
    SDL_RenderPresent(mainRenderer);
    if (willquit) {
      break;
    }
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
 *  This file is part of Poedit (http://www.poedit.net)
 *
 *  Copyright (C) 2008-2013 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "attentionbar.h"

#include <wx/sizer.h>
#include <wx/settings.h>
#include <wx/artprov.h>
#include <wx/bmpbuttn.h>
#include <wx/stattext.h>
#include <wx/statbmp.h>
#include <wx/config.h>
#include <wx/dcclient.h>

#ifdef __WXMAC__
#include "osx_helpers.h"
#endif

#if defined(__WXMSW__)
    #define USE_SLIDE_EFFECT
#endif

#ifdef __WXMAC__
    #define SMALL_BORDER   5
    #define BUTTONS_SPACE 10
#else
    #define SMALL_BORDER   3
    #define BUTTONS_SPACE  3
#endif

BEGIN_EVENT_TABLE(AttentionBar, wxPanel)
    EVT_BUTTON(wxID_CLOSE, AttentionBar::OnClose)
    EVT_BUTTON(wxID_ANY, AttentionBar::OnAction)
END_EVENT_TABLE()

AttentionBar::AttentionBar(wxWindow *parent)
    : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
              wxTAB_TRAVERSAL | wxBORDER_NONE)
{
#ifdef __WXMSW__
    wxColour bg("#FFF499"); // match Visual Studio 2012+'s aesthetics
#else
    wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK);
#endif
    SetBackgroundColour(bg);
    SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));

    m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
    m_label = new wxStaticText(this, wxID_ANY, wxEmptyString);

    m_buttons = new wxBoxSizer(wxHORIZONTAL);

    wxButton *btnClose =
            new wxBitmapButton
                (
                    this, wxID_CLOSE,
                    wxArtProvider::GetBitmap("window-close", wxART_MENU),
                    wxDefaultPosition, wxDefaultSize,
                    wxNO_BORDER
                );
    btnClose->SetToolTip(_("Hide this notification message"));
#ifdef __WXMSW__
    btnClose->SetBackgroundColour(bg);
#endif
#ifdef __WXMAC__
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#endif
#if defined(__WXMAC__) || defined(__WXMSW__)
    Bind(wxEVT_PAINT, &AttentionBar::OnPaint, this);
    wxFont boldFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
    boldFont.SetWeight(wxFONTWEIGHT_BOLD);
    m_label->SetFont(boldFont);
#endif //

    wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
    sizer->AddSpacer(wxSizerFlags::GetDefaultBorder());
    sizer->Add(m_icon, wxSizerFlags().Center().Border(wxRIGHT, SMALL_BORDER));
    sizer->Add(m_label, wxSizerFlags(1).Center().Border(wxALL, SMALL_BORDER));
    sizer->Add(m_buttons, wxSizerFlags().Center().Border(wxALL, SMALL_BORDER));
    sizer->Add(btnClose, wxSizerFlags().Center().Border(wxALL, SMALL_BORDER));

    SetSizer(sizer);

    // the bar should be initially hidden
    Show(false);
}

#ifdef __WXMAC__
void AttentionBar::OnPaint(wxPaintEvent&)
{
    wxPaintDC dc(this);

    wxRect rect(dc.GetSize());

    dc.SetPen(wxColour(254,230,93));
    dc.DrawLine(rect.GetTopLeft(), rect.GetTopRight());
    dc.SetPen(wxColour(176,120,7));
    dc.DrawLine(rect.GetBottomLeft(), rect.GetBottomRight());

    rect.Deflate(0,1);
    dc.GradientFillLinear
       (
         rect,
         wxColour(254,220,48),
         wxColour(253,188,11),
         wxDOWN
       );
}
#endif // __WXMAC__

#ifdef __WXMSW__
void AttentionBar::OnPaint(wxPaintEvent&)
{
    wxPaintDC dc(this);

    wxRect rect(dc.GetSize());
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
    dc.SetPen(wxColour("#e5dd8c"));
    dc.DrawRoundedRectangle(rect, 1);
}
#endif // __WXMSW__

void AttentionBar::ShowMessage(const AttentionMessage& msg)
{
    if ( msg.IsBlacklisted() )
        return;

    wxString iconName;

    switch ( msg.m_kind )
    {
        case AttentionMessage::Info:
            iconName = wxART_INFORMATION;
            break;
        case AttentionMessage::Warning:
            iconName = wxART_WARNING;
            break;
        case AttentionMessage::Error:
            iconName = wxART_ERROR;
            break;
    }

    m_icon->SetBitmap(wxArtProvider::GetBitmap(iconName, wxART_MENU, wxSize(16, 16)));
    m_label->SetLabelText(msg.m_text);

    m_buttons->Clear(true/*delete_windows*/);
    m_actions.clear();

    for ( AttentionMessage::Actions::const_iterator i = msg.m_actions.begin();
          i != msg.m_actions.end(); ++i )
    {
        wxButton *b = new wxButton(this, wxID_ANY, i->first);
#ifdef __WXMAC__
        MakeButtonRounded(b->GetHandle());
#endif
        m_buttons->Add(b, wxSizerFlags().Center().Border(wxRIGHT, BUTTONS_SPACE));
        m_actions[b] = i->second;
    }

    // we need to size the control correctly _and_ lay out the controls if this
    // is the first time it's being shown, otherwise we can get garbled look:
    SetSize(GetParent()->GetClientSize().x,
            GetBestSize().y);
    Layout();

#ifdef USE_SLIDE_EFFECT
    ShowWithEffect(wxSHOW_EFFECT_SLIDE_TO_BOTTOM);
#else
    Show();
#endif
    GetParent()->Layout();
}

void AttentionBar::HideMessage()
{
#ifdef USE_SLIDE_EFFECT
    HideWithEffect(wxSHOW_EFFECT_SLIDE_TO_TOP);
#else
    Hide();
#endif
    GetParent()->Layout();
}

void AttentionBar::OnClose(wxCommandEvent& WXUNUSED(event))
{
    HideMessage();
}

void AttentionBar::OnAction(wxCommandEvent& event)
{
    ActionsMap::const_iterator i = m_actions.find(event.GetEventObject());
    if ( i == m_actions.end() )
    {
        event.Skip();
        return;
    }

    HideMessage();
    i->second();
}

/* static */
void AttentionMessage::AddToBlacklist(const wxString& id)
{
    wxConfig::Get()->Write
        (
            wxString::Format("/messages/dont_show/%s", id.c_str()),
            (long)true
        );
}

/* static */
bool AttentionMessage::IsBlacklisted(const wxString& id)
{
    return wxConfig::Get()->ReadBool
        (
            wxString::Format("/messages/dont_show/%s", id.c_str()),
            false
        );
}

void AttentionMessage::AddDontShowAgain()
{
    AddAction(_("Don't show again"),
              std::bind(&AttentionMessage::AddToBlacklist, m_id));
}
<commit_msg>AttentionBar: don't use ShowWithEffect even on Windows.<commit_after>/*
 *  This file is part of Poedit (http://www.poedit.net)
 *
 *  Copyright (C) 2008-2013 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "attentionbar.h"

#include <wx/sizer.h>
#include <wx/settings.h>
#include <wx/artprov.h>
#include <wx/bmpbuttn.h>
#include <wx/stattext.h>
#include <wx/statbmp.h>
#include <wx/config.h>
#include <wx/dcclient.h>

#ifdef __WXMAC__
#include "osx_helpers.h"
#endif

#ifdef __WXMAC__
    #define SMALL_BORDER   5
    #define BUTTONS_SPACE 10
#else
    #define SMALL_BORDER   3
    #define BUTTONS_SPACE  3
#endif

BEGIN_EVENT_TABLE(AttentionBar, wxPanel)
    EVT_BUTTON(wxID_CLOSE, AttentionBar::OnClose)
    EVT_BUTTON(wxID_ANY, AttentionBar::OnAction)
END_EVENT_TABLE()

AttentionBar::AttentionBar(wxWindow *parent)
    : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
              wxTAB_TRAVERSAL | wxBORDER_NONE)
{
#ifdef __WXMSW__
    wxColour bg("#FFF499"); // match Visual Studio 2012+'s aesthetics
#else
    wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK);
#endif
    SetBackgroundColour(bg);
    SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));

    m_icon = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
    m_label = new wxStaticText(this, wxID_ANY, wxEmptyString);

    m_buttons = new wxBoxSizer(wxHORIZONTAL);

    wxButton *btnClose =
            new wxBitmapButton
                (
                    this, wxID_CLOSE,
                    wxArtProvider::GetBitmap("window-close", wxART_MENU),
                    wxDefaultPosition, wxDefaultSize,
                    wxNO_BORDER
                );
    btnClose->SetToolTip(_("Hide this notification message"));
#ifdef __WXMSW__
    btnClose->SetBackgroundColour(bg);
#endif
#ifdef __WXMAC__
    SetWindowVariant(wxWINDOW_VARIANT_SMALL);
#endif
#if defined(__WXMAC__) || defined(__WXMSW__)
    Bind(wxEVT_PAINT, &AttentionBar::OnPaint, this);
    wxFont boldFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
    boldFont.SetWeight(wxFONTWEIGHT_BOLD);
    m_label->SetFont(boldFont);
#endif //

    wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
    sizer->AddSpacer(wxSizerFlags::GetDefaultBorder());
    sizer->Add(m_icon, wxSizerFlags().Center().Border(wxRIGHT, SMALL_BORDER));
    sizer->Add(m_label, wxSizerFlags(1).Center().Border(wxALL, SMALL_BORDER));
    sizer->Add(m_buttons, wxSizerFlags().Center().Border(wxALL, SMALL_BORDER));
    sizer->Add(btnClose, wxSizerFlags().Center().Border(wxALL, SMALL_BORDER));

    SetSizer(sizer);

    // the bar should be initially hidden
    Show(false);
}

#ifdef __WXMAC__
void AttentionBar::OnPaint(wxPaintEvent&)
{
    wxPaintDC dc(this);

    wxRect rect(dc.GetSize());

    dc.SetPen(wxColour(254,230,93));
    dc.DrawLine(rect.GetTopLeft(), rect.GetTopRight());
    dc.SetPen(wxColour(176,120,7));
    dc.DrawLine(rect.GetBottomLeft(), rect.GetBottomRight());

    rect.Deflate(0,1);
    dc.GradientFillLinear
       (
         rect,
         wxColour(254,220,48),
         wxColour(253,188,11),
         wxDOWN
       );
}
#endif // __WXMAC__

#ifdef __WXMSW__
void AttentionBar::OnPaint(wxPaintEvent&)
{
    wxPaintDC dc(this);

    wxRect rect(dc.GetSize());
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
    dc.SetPen(wxColour("#e5dd8c"));
    dc.DrawRoundedRectangle(rect, 1);
}
#endif // __WXMSW__

void AttentionBar::ShowMessage(const AttentionMessage& msg)
{
    if ( msg.IsBlacklisted() )
        return;

    wxString iconName;

    switch ( msg.m_kind )
    {
        case AttentionMessage::Info:
            iconName = wxART_INFORMATION;
            break;
        case AttentionMessage::Warning:
            iconName = wxART_WARNING;
            break;
        case AttentionMessage::Error:
            iconName = wxART_ERROR;
            break;
    }

    m_icon->SetBitmap(wxArtProvider::GetBitmap(iconName, wxART_MENU, wxSize(16, 16)));
    m_label->SetLabelText(msg.m_text);

    m_buttons->Clear(true/*delete_windows*/);
    m_actions.clear();

    for ( AttentionMessage::Actions::const_iterator i = msg.m_actions.begin();
          i != msg.m_actions.end(); ++i )
    {
        wxButton *b = new wxButton(this, wxID_ANY, i->first);
#ifdef __WXMAC__
        MakeButtonRounded(b->GetHandle());
#endif
        m_buttons->Add(b, wxSizerFlags().Center().Border(wxRIGHT, BUTTONS_SPACE));
        m_actions[b] = i->second;
    }

    // we need to size the control correctly _and_ lay out the controls if this
    // is the first time it's being shown, otherwise we can get garbled look:
    SetSize(GetParent()->GetClientSize().x,
            GetBestSize().y);
    Layout();

    Show();
    GetParent()->Layout();
}

void AttentionBar::HideMessage()
{
    Hide();
    GetParent()->Layout();
}

void AttentionBar::OnClose(wxCommandEvent& WXUNUSED(event))
{
    HideMessage();
}

void AttentionBar::OnAction(wxCommandEvent& event)
{
    ActionsMap::const_iterator i = m_actions.find(event.GetEventObject());
    if ( i == m_actions.end() )
    {
        event.Skip();
        return;
    }

    HideMessage();
    i->second();
}

/* static */
void AttentionMessage::AddToBlacklist(const wxString& id)
{
    wxConfig::Get()->Write
        (
            wxString::Format("/messages/dont_show/%s", id.c_str()),
            (long)true
        );
}

/* static */
bool AttentionMessage::IsBlacklisted(const wxString& id)
{
    return wxConfig::Get()->ReadBool
        (
            wxString::Format("/messages/dont_show/%s", id.c_str()),
            false
        );
}

void AttentionMessage::AddDontShowAgain()
{
    AddAction(_("Don't show again"),
              std::bind(&AttentionMessage::AddToBlacklist, m_id));
}
<|endoftext|>


<commit_before>#include "StructuredDomain.h"
#include <cassert>
using namespace std;

Skeleton::Skeleton(Domain domain): _norient(numOrientations(domain)) {
  assert(_norient > 0);

  _orientations = new DPAG[_norient];
  _top_orders = new (vector<int>)[_orient];
}

Skeleton::~Skeleton() {
  delete[] _orientations;
  delete[] _top_orders;
}
<commit_msg>Initial support for factory method.<commit_after>#include "Instance.h"
#include <cassert>
using namespace std;

// factory method
Instance* Instance::factory(Enum d, Transduction t, std::istream& is)
  throw(BadInstanceCreation) {
  if(type == SEQUENCE) { return new Sequence(d, t, is); }
}

Instance::Skeleton::Skeleton(Domain domain): _i(-1), _o(-1), _norient(num_orientations(domain)) {
  assert(_norient > 0);

  _orientations = new (DPAG*)[_norient];
  _top_orders = new (vector<int>)[_norient];
}

Instance::Skeleton::~Skeleton() {
  for(int i=0; i<_norient; ++i)
    delete _orientations[i];
  delete[] _orientations;

  delete[] _top_orders;
}

<|endoftext|>


<commit_before>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Client.hxx"
#include "event/Duration.hxx"
#include "net/SocketAddress.hxx"
#include "net/Interface.hxx"

#include <daemon/log.h>

#include <avahi-common/error.h>
#include <avahi-common/malloc.h>
#include <avahi-common/alternative.h>

MyAvahiClient::MyAvahiClient(EventLoop &event_loop, const char *_name)
    :name(_name),
     reconnect_timer(event_loop, BIND_THIS_METHOD(OnReconnectTimer)),
     poll(event_loop)
{
}

MyAvahiClient::~MyAvahiClient()
{
    Close();
}

void
MyAvahiClient::AddService(AvahiIfIndex interface, AvahiProtocol protocol,
                          const char *type, uint16_t port)
{
    /* cannot register any more services after initial connect */
    assert(client == nullptr);

    if (services.empty())
        /* initiate the connection */
        reconnect_timer.Add(EventDuration<0, 10000>::value);

    services.emplace_front(interface, protocol, type, port);
}

void
MyAvahiClient::AddService(const char *type, SocketAddress address)
{
    unsigned port = address.GetPort();
    if (port == 0)
        return;

    unsigned i = FindNetworkInterface(address);
    AvahiIfIndex ii = i > 0
        ? AvahiIfIndex(i)
        : AVAHI_IF_UNSPEC;

    AvahiProtocol protocol = AVAHI_PROTO_UNSPEC;
    switch (address.GetFamily()) {
    case AF_INET:
        protocol = AVAHI_PROTO_INET;
        break;

    case AF_INET6:
        protocol = AVAHI_PROTO_INET6;
        break;
    }

    AddService(ii, protocol, type, port);
}

void
MyAvahiClient::Close()
{
    if (group != nullptr) {
        avahi_entry_group_free(group);
        group = nullptr;
    }

    if (client != nullptr)
        avahi_client_free(client);
}

void
MyAvahiClient::GroupCallback(AvahiEntryGroup *g, AvahiEntryGroupState state)
{
    switch (state) {
    case AVAHI_ENTRY_GROUP_ESTABLISHED:
        break;

    case AVAHI_ENTRY_GROUP_COLLISION:
        /* pick a new name */

        {
            char *new_name = avahi_alternative_service_name(name.c_str());
            name = new_name;
            avahi_free(new_name);
        }

        /* And recreate the services */
        RegisterServices(avahi_entry_group_get_client(g));
        break;

    case AVAHI_ENTRY_GROUP_FAILURE:
        daemon_log(3, "Avahi service group failure: %s",
                   avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
        break;

    case AVAHI_ENTRY_GROUP_UNCOMMITED:
    case AVAHI_ENTRY_GROUP_REGISTERING:
        break;
    }
}

void
MyAvahiClient::GroupCallback(AvahiEntryGroup *g,
                             AvahiEntryGroupState state,
                             void *userdata)
{
    auto &client = *(MyAvahiClient *)userdata;
    client.GroupCallback(g, state);
}

void
MyAvahiClient::RegisterServices(AvahiClient *c)
{
    if (group == nullptr) {
        group = avahi_entry_group_new(c, GroupCallback, this);
        if (group == nullptr) {
            daemon_log(3, "Failed to create Avahi service group: %s",
                       avahi_strerror(avahi_client_errno(c)));
            return;
        }
    }

    for (const auto &i : services) {
        int error = avahi_entry_group_add_service(group,
                                                  AVAHI_IF_UNSPEC,
                                                  AVAHI_PROTO_UNSPEC,
                                                  AvahiPublishFlags(0),
                                                  name.c_str(), i.type.c_str(),
                                                  nullptr, nullptr,
                                                  i.port, nullptr);
        if (error < 0) {
            daemon_log(3, "Failed to add Avahi service %s: %s",
                       i.type.c_str(), avahi_strerror(error));
            return;
        }
    }

    int result = avahi_entry_group_commit(group);
    if (result < 0) {
        daemon_log(3, "Failed to commit Avahi service group: %s",
                   avahi_strerror(result));
        return;
    }
}

void
MyAvahiClient::ClientCallback(AvahiClient *c, AvahiClientState state)
{
    int error;

    switch (state) {
    case AVAHI_CLIENT_S_RUNNING:
        if (group == nullptr)
            RegisterServices(c);
        break;

    case AVAHI_CLIENT_FAILURE:
        error = avahi_client_errno(c);
        if (error == AVAHI_ERR_DISCONNECTED) {
            Close();

            reconnect_timer.Add(EventDuration<10, 0>::value);
        } else {
            daemon_log(3, "Avahi client failed: %s", avahi_strerror(error));
            reconnect_timer.Add(EventDuration<60, 0>::value);
        }

        break;

    case AVAHI_CLIENT_S_COLLISION:
    case AVAHI_CLIENT_S_REGISTERING:
        if (group != nullptr)
            avahi_entry_group_reset(group);

        break;

    case AVAHI_CLIENT_CONNECTING:
        break;
    }
}

void
MyAvahiClient::ClientCallback(AvahiClient *c, AvahiClientState state,
                              void *userdata)
{
    auto &client = *(MyAvahiClient *)userdata;
    client.ClientCallback(c, state);
}

void
MyAvahiClient::OnReconnectTimer()
{
    int error;
    client = avahi_client_new(&poll, AVAHI_CLIENT_NO_FAIL,
                              ClientCallback, this,
                              &error);
    if (client == nullptr) {
        daemon_log(3, "Failed to create avahi client: %s",
                   avahi_strerror(error));
        reconnect_timer.Add(EventDuration<60, 0>::value);
        return;
    }
}
<commit_msg>avahi/Client: add missing newlines to log messages<commit_after>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Client.hxx"
#include "event/Duration.hxx"
#include "net/SocketAddress.hxx"
#include "net/Interface.hxx"

#include <daemon/log.h>

#include <avahi-common/error.h>
#include <avahi-common/malloc.h>
#include <avahi-common/alternative.h>

MyAvahiClient::MyAvahiClient(EventLoop &event_loop, const char *_name)
    :name(_name),
     reconnect_timer(event_loop, BIND_THIS_METHOD(OnReconnectTimer)),
     poll(event_loop)
{
}

MyAvahiClient::~MyAvahiClient()
{
    Close();
}

void
MyAvahiClient::AddService(AvahiIfIndex interface, AvahiProtocol protocol,
                          const char *type, uint16_t port)
{
    /* cannot register any more services after initial connect */
    assert(client == nullptr);

    if (services.empty())
        /* initiate the connection */
        reconnect_timer.Add(EventDuration<0, 10000>::value);

    services.emplace_front(interface, protocol, type, port);
}

void
MyAvahiClient::AddService(const char *type, SocketAddress address)
{
    unsigned port = address.GetPort();
    if (port == 0)
        return;

    unsigned i = FindNetworkInterface(address);
    AvahiIfIndex ii = i > 0
        ? AvahiIfIndex(i)
        : AVAHI_IF_UNSPEC;

    AvahiProtocol protocol = AVAHI_PROTO_UNSPEC;
    switch (address.GetFamily()) {
    case AF_INET:
        protocol = AVAHI_PROTO_INET;
        break;

    case AF_INET6:
        protocol = AVAHI_PROTO_INET6;
        break;
    }

    AddService(ii, protocol, type, port);
}

void
MyAvahiClient::Close()
{
    if (group != nullptr) {
        avahi_entry_group_free(group);
        group = nullptr;
    }

    if (client != nullptr)
        avahi_client_free(client);
}

void
MyAvahiClient::GroupCallback(AvahiEntryGroup *g, AvahiEntryGroupState state)
{
    switch (state) {
    case AVAHI_ENTRY_GROUP_ESTABLISHED:
        break;

    case AVAHI_ENTRY_GROUP_COLLISION:
        /* pick a new name */

        {
            char *new_name = avahi_alternative_service_name(name.c_str());
            name = new_name;
            avahi_free(new_name);
        }

        /* And recreate the services */
        RegisterServices(avahi_entry_group_get_client(g));
        break;

    case AVAHI_ENTRY_GROUP_FAILURE:
        daemon_log(3, "Avahi service group failure: %s\n",
                   avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
        break;

    case AVAHI_ENTRY_GROUP_UNCOMMITED:
    case AVAHI_ENTRY_GROUP_REGISTERING:
        break;
    }
}

void
MyAvahiClient::GroupCallback(AvahiEntryGroup *g,
                             AvahiEntryGroupState state,
                             void *userdata)
{
    auto &client = *(MyAvahiClient *)userdata;
    client.GroupCallback(g, state);
}

void
MyAvahiClient::RegisterServices(AvahiClient *c)
{
    if (group == nullptr) {
        group = avahi_entry_group_new(c, GroupCallback, this);
        if (group == nullptr) {
            daemon_log(3, "Failed to create Avahi service group: %s\n",
                       avahi_strerror(avahi_client_errno(c)));
            return;
        }
    }

    for (const auto &i : services) {
        int error = avahi_entry_group_add_service(group,
                                                  AVAHI_IF_UNSPEC,
                                                  AVAHI_PROTO_UNSPEC,
                                                  AvahiPublishFlags(0),
                                                  name.c_str(), i.type.c_str(),
                                                  nullptr, nullptr,
                                                  i.port, nullptr);
        if (error < 0) {
            daemon_log(3, "Failed to add Avahi service %s: %s\n",
                       i.type.c_str(), avahi_strerror(error));
            return;
        }
    }

    int result = avahi_entry_group_commit(group);
    if (result < 0) {
        daemon_log(3, "Failed to commit Avahi service group: %s\n",
                   avahi_strerror(result));
        return;
    }
}

void
MyAvahiClient::ClientCallback(AvahiClient *c, AvahiClientState state)
{
    int error;

    switch (state) {
    case AVAHI_CLIENT_S_RUNNING:
        if (group == nullptr)
            RegisterServices(c);
        break;

    case AVAHI_CLIENT_FAILURE:
        error = avahi_client_errno(c);
        if (error == AVAHI_ERR_DISCONNECTED) {
            Close();

            reconnect_timer.Add(EventDuration<10, 0>::value);
        } else {
            daemon_log(3, "Avahi client failed: %s\n", avahi_strerror(error));
            reconnect_timer.Add(EventDuration<60, 0>::value);
        }

        break;

    case AVAHI_CLIENT_S_COLLISION:
    case AVAHI_CLIENT_S_REGISTERING:
        if (group != nullptr)
            avahi_entry_group_reset(group);

        break;

    case AVAHI_CLIENT_CONNECTING:
        break;
    }
}

void
MyAvahiClient::ClientCallback(AvahiClient *c, AvahiClientState state,
                              void *userdata)
{
    auto &client = *(MyAvahiClient *)userdata;
    client.ClientCallback(c, state);
}

void
MyAvahiClient::OnReconnectTimer()
{
    int error;
    client = avahi_client_new(&poll, AVAHI_CLIENT_NO_FAIL,
                              ClientCallback, this,
                              &error);
    if (client == nullptr) {
        daemon_log(3, "Failed to create avahi client: %s\n",
                   avahi_strerror(error));
        reconnect_timer.Add(EventDuration<60, 0>::value);
        return;
    }
}
<|endoftext|>


<commit_before>#include "cosmology.hpp"
#include <math.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_odeiv2.h>
#include <gsl/gsl_errno.h>
#include "physconst.h"
#include <valarray>
#include <cassert>

/**This file contains code to compute the Hubble function at arbitrary redshift. Most of the code integrates
 * Omega_Nu for massive neutrinos, taken from the Gadget-3 patches..**/

/* We need to include radiation to get the early-time growth factor right,
 * which comes into the Zel'dovich approximation.*/
/* Omega_g = 4 \sigma_B T_{CMB}^4 8 \pi G / (3 c^3 H^2)*/
#define OMEGAG (4*STEFAN_BOLTZMANN*8*M_PI*GRAVITY/(3*LIGHTCGS*LIGHTCGS*LIGHTCGS*HUBBLE*HUBBLE*HubbleParam*HubbleParam)*pow(T_CMB0,4))
//Neutrino mass splittings
#define M21 7.53e-5 //Particle data group 2016: +- 0.18e-5 eV2
#define M32n 2.44e-3 //Particle data group: +- 0.06e-3 eV2
#define M32i 2.51e-3 //Particle data group: +- 0.06e-3 eV2
//(this is different for normal and inverted hierarchy)

/* Compute the three neutrino masses,
 * including the neutrino mass splittings
 * from oscillation experiments.
 * mnu is the total neutrino mass in eV.
 * Hierarchy is -1 for inverted (two heavy),
 * 1 for normal (two light) and 0 for degenerate.*/
std::valarray<double> NuPartMasses(double mnu, int Hierarchy)
{
    std::valarray<double> numasses(mnu/3.,3);
    //Hierarchy == 0 is 3 degenerate neutrinos
    if(Hierarchy == 0)
        return numasses;

    const double M32 = Hierarchy > 0 ? M32n : -M32i;
    //If the total mass is below that allowed by the hierarchy,
    //assume one active neutrino.
    if(mnu < ((Hierarchy > 0) ? sqrt(M32n) + sqrt(M21) : 2*sqrt(M32i) -sqrt(M21))) {
        return std::valarray<double> ({mnu, 0, 0});
    }
    //DD is the summed masses of the two closest neutrinos
    double DD1 = 4 * mnu/3. - 2/3.*sqrt(mnu*mnu + 3*M32 + 1.5*M21);
    //Last term was neglected initially. This should be very well converged.
    double DD = 4 * mnu/3. - 2/3.*sqrt(mnu*mnu + 3*M32 + 1.5*M21 + 0.75*M21*M21/DD1/DD1);
    assert(std::isfinite(DD));
    assert(fabs(DD1/DD -1) < 1e-2);
    numasses[0] = mnu - DD;
    numasses[1] = 0.5*(DD + M21/DD);
    numasses[2] = 0.5*(DD - M21/DD);
    return numasses;
}

//Hubble H(z) / H0 in units of 1/T.
double Cosmology::Hubble(double a)
{
        //Begin with curvature and lambda.
        double hubble_a = OmegaMatter(a);
        //curvature and lambda
        hubble_a += (1 - Omega - OmegaLambda) / (a * a) + OmegaLambda;
        //Add the radiation, including neutrinos
        hubble_a += OmegaR(a);
        return HUBBLE * sqrt(hubble_a);
}

/* Return the total matter density in neutrinos.
* rho_nu and friends are not externally callable*/
double Cosmology::OmegaNu(double a)
{
        double rhonu = 0;
        auto numasses = NuPartMasses(MNu, Hierarchy);
        for(int i=0; i<3;i++){
            rhonu += OmegaNu_single(a,numasses[i]);
        }
        return rhonu;
}

double Cosmology::OmegaMatter(double a)
{
    double OmegaM = Omega;
    /* Do not include neutrinos
     * in the source term of the growth function
     * in growth_ode, unless they are already not
     * free-streaming. This is not right if
     * our box overlaps with their free-streaming scale.
     * In that case the growth factor will be scale-dependent.
     * In practice the box will either be larger
     * than the horizon, which is not accurate anyway, or the neutrino
     * mass will be larger than current constraints allow,
     * so we don't worry about it too much.*/
    if(MNu > 0) {
       OmegaM -= OmegaNu(1);
       if (!NeutrinosFreeStreaming)
          OmegaM += OmegaNu(a);
    }
    return OmegaM/(a * a * a);
}

double Cosmology::OmegaR(double a)
{
    if(NoRadiation)
        return 0;
    double omr = OMEGAG/(a*a*a*a);
    //Neutrinos are included in the radiation,
    //unless they are massive and not free-streaming
    if(MNu == 0 || NeutrinosFreeStreaming)
      omr += OmegaNu(a);
    return omr;
}

bool Cosmology::SetNeutrinoFreeStream(double box, double v_th, double a)
{
    /*Neutrino free-streaming length from Lesgourgues & Pastor*/
    double nufs = 2 * M_PI * sqrt(2/3.) * v_th / Hubble(a)/a;
    NeutrinosFreeStreaming = nufs > box/4.;
    if(!NeutrinosFreeStreaming)
        fprintf(stderr,"WARNING: Neutrino free-streaming at %g boxes. May be inaccurate as scale-dependent growth is not modelled.\n",nufs/box);
    return NeutrinosFreeStreaming;
}

/*Note q carries units of eV/c. kT/c has units of eV/c.
 * M_nu has units of eV  Here c=1. */
double rho_nu_int(double q, void * params)
{
        double amnu = *((double *)params);
        double epsilon = sqrt(q*q+amnu*amnu);
        double f0 = 1./(exp(q/(BOLEVK*TNU))+1);
        return q*q*epsilon*f0;
}

/* Tables for rho_nu: stores precomputed values between
 * simulation start and a M_nu = 20 kT_nu*/
#define GSL_VAL 200
/*Get the conversion factor to go from (eV/c)^4 to g/cm^3
 * for a **single** neutrino species. */
double get_rho_nu_conversion()
{
        /*q has units of eV/c, so rho_nu now has units of (eV/c)^4*/
        double convert=4*M_PI*2; /* The factor of two is for antineutrinos*/
        /*rho_nu_val now has units of eV^4*/
        /*To get units of density, divide by (c*hbar)**3 in eV s and cm/s */
        const double chbar=1./(2*M_PI*LIGHTCGS*HBAR);
        convert*=(chbar*chbar*chbar);
        /*Now has units of (eV)/(cm^3)*/
        /* 1 eV = 1.60217646 × 10-12 g cm^2 s^(-2) */
        /* So 1eV/c^2 = 1.7826909604927859e-33 g*/
        /*So this is rho_nu_val in g /cm^3*/
        convert*=(1.60217646e-12/LIGHTCGS/LIGHTCGS);
        return convert;
}

/*Integrated value of rho_nu for regions between relativistic and non-relativistic*/
double integrate_rho_nu(double a,double mnu)
{
     double abserr;
     double amnu = a*mnu;
     gsl_function F;
     gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_VAL);
     F.function = &rho_nu_int;
     F.params = &amnu;
     double rhonu;
     gsl_integration_qag (&F, 0, 500*BOLEVK*TNU,0 , 1e-9,GSL_VAL,6,w,&rhonu, &abserr);
     rhonu=rhonu/pow(a,4)*get_rho_nu_conversion();
     gsl_integration_workspace_free (w);
     return rhonu;
}

/* Value of kT/aM_nu on which to switch from the
 * analytic expansion to the numerical integration*/
#define NU_SW 50
//1.878 82(24) x 10-29 h02 g/cm3 = 1.053 94(13) x 104 h02 eV/cm3
/*Finds the physical density in neutrinos for a single neutrino species*/
double rho_nu(double a,double mnu)
{
        double rho_nu_val;
        double amnu=a*mnu;
        const double kT=BOLEVK*TNU;
        const double kTamnu2=(kT*kT/amnu/amnu);
        /*Do it analytically if we are in a regime where we can
         * The next term is 141682 (kT/amnu)^8.
         * At kT/amnu = 8, higher terms are larger and the series stops converging.
         * Don't go lower than 50 here. */
        if(NU_SW*NU_SW*kTamnu2 < 1){
            /*Heavily non-relativistic*/
            /*The constants are Riemann zetas: 3,5,7 respectively*/
            rho_nu_val=mnu*pow(kT/a,3)*(1.5*1.202056903159594+kTamnu2*45./4.*1.0369277551433704+2835./32.*kTamnu2*kTamnu2*1.0083492773819229+80325/32.*kTamnu2*kTamnu2*kTamnu2*1.0020083928260826)*get_rho_nu_conversion();
        }
        else if(amnu < 1e-6*kT){
            /*Heavily relativistic: we could be more accurate here,
             * but in practice this will only be called for massless neutrinos, so don't bother.*/
            rho_nu_val=7*pow(M_PI*kT/a,4)/120.*get_rho_nu_conversion();
        }
        else{
            rho_nu_val = integrate_rho_nu(a,mnu);
        }
        return rho_nu_val;
}

/* Return the matter density in a single neutrino species.
* Not externally callable*/
double Cosmology::OmegaNu_single(double a,double mnu)
{
        double rhonu;
        rhonu=rho_nu(a,mnu);
        rhonu /= (3* HUBBLE* HUBBLE / (8 * M_PI * GRAVITY));
        rhonu /= HubbleParam*HubbleParam;
        return rhonu;
}

double Cosmology::GrowthFactor(double astart, double aend)
{
  return growth(aend, NULL) / growth(astart, NULL);
}

int growth_ode(double a, const double yy[], double dyda[], void * param)
{
    Cosmology * d_this = (Cosmology *) param;
    const double hub = d_this->Hubble(a)/HUBBLE;
    dyda[0] = yy[1]/pow(a,3)/hub;
    /*We want neutrinos to be non-relativistic, as only this part gravitates*/
    dyda[1] = yy[0] * 1.5 * a * d_this->OmegaMatter(a) / hub;
    return GSL_SUCCESS;
}

/** The growth function is given as a 2nd order DE in Peacock 1999, Cosmological Physics.
 * D'' + a'/a D' - 1.5 * (a'/a)^2 D = 0
 * 1/a (a D')' - 1.5 (a'/a)^2 D
 * where ' is d/d tau = a^2 H d/da
 * Define F = a^3 H dD/da
 * and we have: dF/da = 1.5 a H D
 */
double Cosmology::growth(double a, double * dDda)
{
  gsl_odeiv2_system FF;
  FF.function = &growth_ode;
  FF.jacobian = NULL;
  FF.dimension = 2;
  //Just pass the whole structure as the params pointer, as GSL won't let us make the integrand a member function
  FF.params = this;
  gsl_odeiv2_driver * drive = gsl_odeiv2_driver_alloc_standard_new(&FF,gsl_odeiv2_step_rkf45, 1e-5, 1e-8,1e-8,1,1);
   /* We start early to avoid lambda.*/
  double curtime = 1e-5;
  /* Initial velocity chosen so that D = Omegar + 3/2 Omega_m a,
   * the solution for a matter/radiation universe.*
   * Note the normalisation of D is arbitrary
   * and never seen outside this function.*/
  double yinit[2] = {OmegaR(curtime) + 1.5 * OmegaMatter(curtime)*curtime, pow(curtime,3)*Hubble(curtime)/HUBBLE * 1.5 * OmegaMatter(curtime)};
  int stat = gsl_odeiv2_driver_apply(drive, &curtime,a, yinit);
  if (stat != GSL_SUCCESS) {
      printf("gsl_odeiv in growth: %d. Result at %g is %g %g\n",stat, curtime, yinit[0], yinit[1]);
  }
  gsl_odeiv2_driver_free(drive);
  /*Store derivative of D if needed.*/
  if(dDda) {
      *dDda = yinit[1]/pow(a,3)/(Hubble(a)/HUBBLE);
  }
  return yinit[0];
}

/*
 * This is the Zeldovich approximation prefactor,
 * f1 = d ln D1 / dlna = a / D (dD/da)
 */
double Cosmology::F_Omega(double a)
{
    double dD1da=0;
    double D1 = growth(a, &dD1da);
    return a / D1 * dD1da;
}

/* The 2LPT prefactor, f2 = d ln D2/dlna.
 * This is an approximation rather than the exact result,
 * and not strictly valid for closed universes.
 * The approximation should be good enough since
 * the 2lpt term is generally small.
 */
double Cosmology::F2_Omega(double a)
{
  double omega_a;
  omega_a = Omega / (Omega + a * (1 - Omega - OmegaLambda) + a * a * a * OmegaLambda);
  if (1 - Omega - OmegaLambda < 0)
      return 2 * pow(omega_a, 4./7.);
  else
      return 2 * pow(omega_a, 6./11.);
}

<commit_msg>Check derived neutrino mass is positive<commit_after>#include "cosmology.hpp"
#include <math.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_odeiv2.h>
#include <gsl/gsl_errno.h>
#include "physconst.h"
#include <valarray>
#include <cassert>

/**This file contains code to compute the Hubble function at arbitrary redshift. Most of the code integrates
 * Omega_Nu for massive neutrinos, taken from the Gadget-3 patches..**/

/* We need to include radiation to get the early-time growth factor right,
 * which comes into the Zel'dovich approximation.*/
/* Omega_g = 4 \sigma_B T_{CMB}^4 8 \pi G / (3 c^3 H^2)*/
#define OMEGAG (4*STEFAN_BOLTZMANN*8*M_PI*GRAVITY/(3*LIGHTCGS*LIGHTCGS*LIGHTCGS*HUBBLE*HUBBLE*HubbleParam*HubbleParam)*pow(T_CMB0,4))
//Neutrino mass splittings
#define M21 7.53e-5 //Particle data group 2016: +- 0.18e-5 eV2
#define M32n 2.44e-3 //Particle data group: +- 0.06e-3 eV2
#define M32i 2.51e-3 //Particle data group: +- 0.06e-3 eV2
//(this is different for normal and inverted hierarchy)

/* Compute the three neutrino masses,
 * including the neutrino mass splittings
 * from oscillation experiments.
 * mnu is the total neutrino mass in eV.
 * Hierarchy is -1 for inverted (two heavy),
 * 1 for normal (two light) and 0 for degenerate.*/
std::valarray<double> NuPartMasses(double mnu, int Hierarchy)
{
    std::valarray<double> numasses(mnu/3.,3);
    //Hierarchy == 0 is 3 degenerate neutrinos
    if(Hierarchy == 0)
        return numasses;

    const double M32 = Hierarchy > 0 ? M32n : -M32i;
    //If the total mass is below that allowed by the hierarchy,
    //assume one active neutrino.
    if(mnu < ((Hierarchy > 0) ? sqrt(M32n) + sqrt(M21) : 2*sqrt(M32i) -sqrt(M21))) {
        return std::valarray<double> ({mnu, 0, 0});
    }
    //DD is the summed masses of the two closest neutrinos
    double DD1 = 4 * mnu/3. - 2/3.*sqrt(mnu*mnu + 3*M32 + 1.5*M21);
    //Last term was neglected initially. This should be very well converged.
    double DD = 4 * mnu/3. - 2/3.*sqrt(mnu*mnu + 3*M32 + 1.5*M21 + 0.75*M21*M21/DD1/DD1);
    assert(std::isfinite(DD));
    assert(fabs(DD1/DD -1) < 2e-2);
    numasses[0] = mnu - DD;
    numasses[1] = 0.5*(DD + M21/DD);
    numasses[2] = 0.5*(DD - M21/DD);
    assert(numasses[2] > 0);
    return numasses;
}

//Hubble H(z) / H0 in units of 1/T.
double Cosmology::Hubble(double a)
{
        //Begin with curvature and lambda.
        double hubble_a = OmegaMatter(a);
        //curvature and lambda
        hubble_a += (1 - Omega - OmegaLambda) / (a * a) + OmegaLambda;
        //Add the radiation, including neutrinos
        hubble_a += OmegaR(a);
        return HUBBLE * sqrt(hubble_a);
}

/* Return the total matter density in neutrinos.
* rho_nu and friends are not externally callable*/
double Cosmology::OmegaNu(double a)
{
        double rhonu = 0;
        auto numasses = NuPartMasses(MNu, Hierarchy);
        for(int i=0; i<3;i++){
            rhonu += OmegaNu_single(a,numasses[i]);
        }
        return rhonu;
}

double Cosmology::OmegaMatter(double a)
{
    double OmegaM = Omega;
    /* Do not include neutrinos
     * in the source term of the growth function
     * in growth_ode, unless they are already not
     * free-streaming. This is not right if
     * our box overlaps with their free-streaming scale.
     * In that case the growth factor will be scale-dependent.
     * In practice the box will either be larger
     * than the horizon, which is not accurate anyway, or the neutrino
     * mass will be larger than current constraints allow,
     * so we don't worry about it too much.*/
    if(MNu > 0) {
       OmegaM -= OmegaNu(1);
       if (!NeutrinosFreeStreaming)
          OmegaM += OmegaNu(a);
    }
    return OmegaM/(a * a * a);
}

double Cosmology::OmegaR(double a)
{
    if(NoRadiation)
        return 0;
    double omr = OMEGAG/(a*a*a*a);
    //Neutrinos are included in the radiation,
    //unless they are massive and not free-streaming
    if(MNu == 0 || NeutrinosFreeStreaming)
      omr += OmegaNu(a);
    return omr;
}

bool Cosmology::SetNeutrinoFreeStream(double box, double v_th, double a)
{
    /*Neutrino free-streaming length from Lesgourgues & Pastor*/
    double nufs = 2 * M_PI * sqrt(2/3.) * v_th / Hubble(a)/a;
    NeutrinosFreeStreaming = nufs > box/4.;
    if(!NeutrinosFreeStreaming)
        fprintf(stderr,"WARNING: Neutrino free-streaming at %g boxes. May be inaccurate as scale-dependent growth is not modelled.\n",nufs/box);
    return NeutrinosFreeStreaming;
}

/*Note q carries units of eV/c. kT/c has units of eV/c.
 * M_nu has units of eV  Here c=1. */
double rho_nu_int(double q, void * params)
{
        double amnu = *((double *)params);
        double epsilon = sqrt(q*q+amnu*amnu);
        double f0 = 1./(exp(q/(BOLEVK*TNU))+1);
        return q*q*epsilon*f0;
}

/* Tables for rho_nu: stores precomputed values between
 * simulation start and a M_nu = 20 kT_nu*/
#define GSL_VAL 200
/*Get the conversion factor to go from (eV/c)^4 to g/cm^3
 * for a **single** neutrino species. */
double get_rho_nu_conversion()
{
        /*q has units of eV/c, so rho_nu now has units of (eV/c)^4*/
        double convert=4*M_PI*2; /* The factor of two is for antineutrinos*/
        /*rho_nu_val now has units of eV^4*/
        /*To get units of density, divide by (c*hbar)**3 in eV s and cm/s */
        const double chbar=1./(2*M_PI*LIGHTCGS*HBAR);
        convert*=(chbar*chbar*chbar);
        /*Now has units of (eV)/(cm^3)*/
        /* 1 eV = 1.60217646 × 10-12 g cm^2 s^(-2) */
        /* So 1eV/c^2 = 1.7826909604927859e-33 g*/
        /*So this is rho_nu_val in g /cm^3*/
        convert*=(1.60217646e-12/LIGHTCGS/LIGHTCGS);
        return convert;
}

/*Integrated value of rho_nu for regions between relativistic and non-relativistic*/
double integrate_rho_nu(double a,double mnu)
{
     double abserr;
     double amnu = a*mnu;
     gsl_function F;
     gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_VAL);
     F.function = &rho_nu_int;
     F.params = &amnu;
     double rhonu;
     gsl_integration_qag (&F, 0, 500*BOLEVK*TNU,0 , 1e-9,GSL_VAL,6,w,&rhonu, &abserr);
     rhonu=rhonu/pow(a,4)*get_rho_nu_conversion();
     gsl_integration_workspace_free (w);
     return rhonu;
}

/* Value of kT/aM_nu on which to switch from the
 * analytic expansion to the numerical integration*/
#define NU_SW 50
//1.878 82(24) x 10-29 h02 g/cm3 = 1.053 94(13) x 104 h02 eV/cm3
/*Finds the physical density in neutrinos for a single neutrino species*/
double rho_nu(double a,double mnu)
{
        double rho_nu_val;
        double amnu=a*mnu;
        const double kT=BOLEVK*TNU;
        const double kTamnu2=(kT*kT/amnu/amnu);
        /*Do it analytically if we are in a regime where we can
         * The next term is 141682 (kT/amnu)^8.
         * At kT/amnu = 8, higher terms are larger and the series stops converging.
         * Don't go lower than 50 here. */
        if(NU_SW*NU_SW*kTamnu2 < 1){
            /*Heavily non-relativistic*/
            /*The constants are Riemann zetas: 3,5,7 respectively*/
            rho_nu_val=mnu*pow(kT/a,3)*(1.5*1.202056903159594+kTamnu2*45./4.*1.0369277551433704+2835./32.*kTamnu2*kTamnu2*1.0083492773819229+80325/32.*kTamnu2*kTamnu2*kTamnu2*1.0020083928260826)*get_rho_nu_conversion();
        }
        else if(amnu < 1e-6*kT){
            /*Heavily relativistic: we could be more accurate here,
             * but in practice this will only be called for massless neutrinos, so don't bother.*/
            rho_nu_val=7*pow(M_PI*kT/a,4)/120.*get_rho_nu_conversion();
        }
        else{
            rho_nu_val = integrate_rho_nu(a,mnu);
        }
        return rho_nu_val;
}

/* Return the matter density in a single neutrino species.
* Not externally callable*/
double Cosmology::OmegaNu_single(double a,double mnu)
{
        double rhonu;
        rhonu=rho_nu(a,mnu);
        rhonu /= (3* HUBBLE* HUBBLE / (8 * M_PI * GRAVITY));
        rhonu /= HubbleParam*HubbleParam;
        return rhonu;
}

double Cosmology::GrowthFactor(double astart, double aend)
{
  return growth(aend, NULL) / growth(astart, NULL);
}

int growth_ode(double a, const double yy[], double dyda[], void * param)
{
    Cosmology * d_this = (Cosmology *) param;
    const double hub = d_this->Hubble(a)/HUBBLE;
    dyda[0] = yy[1]/pow(a,3)/hub;
    /*We want neutrinos to be non-relativistic, as only this part gravitates*/
    dyda[1] = yy[0] * 1.5 * a * d_this->OmegaMatter(a) / hub;
    return GSL_SUCCESS;
}

/** The growth function is given as a 2nd order DE in Peacock 1999, Cosmological Physics.
 * D'' + a'/a D' - 1.5 * (a'/a)^2 D = 0
 * 1/a (a D')' - 1.5 (a'/a)^2 D
 * where ' is d/d tau = a^2 H d/da
 * Define F = a^3 H dD/da
 * and we have: dF/da = 1.5 a H D
 */
double Cosmology::growth(double a, double * dDda)
{
  gsl_odeiv2_system FF;
  FF.function = &growth_ode;
  FF.jacobian = NULL;
  FF.dimension = 2;
  //Just pass the whole structure as the params pointer, as GSL won't let us make the integrand a member function
  FF.params = this;
  gsl_odeiv2_driver * drive = gsl_odeiv2_driver_alloc_standard_new(&FF,gsl_odeiv2_step_rkf45, 1e-5, 1e-8,1e-8,1,1);
   /* We start early to avoid lambda.*/
  double curtime = 1e-5;
  /* Initial velocity chosen so that D = Omegar + 3/2 Omega_m a,
   * the solution for a matter/radiation universe.*
   * Note the normalisation of D is arbitrary
   * and never seen outside this function.*/
  double yinit[2] = {OmegaR(curtime) + 1.5 * OmegaMatter(curtime)*curtime, pow(curtime,3)*Hubble(curtime)/HUBBLE * 1.5 * OmegaMatter(curtime)};
  int stat = gsl_odeiv2_driver_apply(drive, &curtime,a, yinit);
  if (stat != GSL_SUCCESS) {
      printf("gsl_odeiv in growth: %d. Result at %g is %g %g\n",stat, curtime, yinit[0], yinit[1]);
  }
  gsl_odeiv2_driver_free(drive);
  /*Store derivative of D if needed.*/
  if(dDda) {
      *dDda = yinit[1]/pow(a,3)/(Hubble(a)/HUBBLE);
  }
  return yinit[0];
}

/*
 * This is the Zeldovich approximation prefactor,
 * f1 = d ln D1 / dlna = a / D (dD/da)
 */
double Cosmology::F_Omega(double a)
{
    double dD1da=0;
    double D1 = growth(a, &dD1da);
    return a / D1 * dD1da;
}

/* The 2LPT prefactor, f2 = d ln D2/dlna.
 * This is an approximation rather than the exact result,
 * and not strictly valid for closed universes.
 * The approximation should be good enough since
 * the 2lpt term is generally small.
 */
double Cosmology::F2_Omega(double a)
{
  double omega_a;
  omega_a = Omega / (Omega + a * (1 - Omega - OmegaLambda) + a * a * a * OmegaLambda);
  if (1 - Omega - OmegaLambda < 0)
      return 2 * pow(omega_a, 4./7.);
  else
      return 2 * pow(omega_a, 6./11.);
}

<|endoftext|>


<commit_before>/*
 * Class to make list of available lessons.
 * source available at (Github repo - MIT licence):
 * http://dstjrd.ir/s/cppx
 * https://github.com/mohsend/cpp-examples
 */

// این کلاس فقط برای این ساخته شده که لیستی از دروس ارایه شده را در اختیار کد اصلی بگذارد
// در یک مثال واقعی این اطلاعات در دیتابیس ذخیره میشوند و از آنجا لود میشوند. نه از یک فایل هدر
#ifndef LIST_OF_LESSONS_HPP
#define LIST_OF_LESSONS_HPP 1

#include <string>
#include "Clesson.hpp"

using namespace std;

class listOfLessons
{
  private:
    // یک آرایه از کلاس درس برای ذخیره واحد های ارایه شده
    Clesson lessons[14];
  public:
    listOfLessons();
    Clesson getLessonByCode(unsigned int);
    void listAll();
};

// مقدار دهی به اجزای آرایه
listOfLessons::listOfLessons()
{
  int index = 0;
  lessons[index++].setDetails("Persian literature", "Daemi", 2, 0, true);
  lessons[index++].setDetails("C++ fundamentals", "Pur ganji", 4, 0, true);
  lessons[index++].setDetails("maths 1", "Reza", 3, 0, true);
  lessons[index++].setDetails("maths 1", "Zia manesh", 3, 0, true);
  lessons[index++].setDetails("maths 2", "Reza", 3, 0, true);
  lessons[index++].setDetails("maths 2", "Zia manesh", 3, 0, true);
  lessons[index++].setDetails("physics 1", "Ghafari", 3, 0, true);
  lessons[index++].setDetails("physics 2", "Ghafari", 3, 0, true);
  lessons[index++].setDetails("phy lab 1", "", 1, 0, false);
  lessons[index++].setDetails("phy lab 2", "Salehi", 1, 0, false);
  lessons[index++].setDetails("history", "", 2, 0, true);
  lessons[index++].setDetails("object oriented programming", "Farhadi", 3, 0, true);
}

// لیست کردن تمام درس های ارایه شده.
void listOfLessons::listAll()
{
  for (unsigned int i = 0; i < 10; i++)
  {
    string theory = (lessons[i].getTheory()) ? "Theory" : "Applied";
    cout << i + 1 << ") " << lessons[i].getName() << " by Prof. " << lessons[i].getLecturer() << " (" << lessons[i].getUnits()  << ' ' << theory << " units)" << endl;
  }
}

// متد ای برای گرفتن درس ارایه شده به صورت یک نمونه از کلاس درس با استفاده از کد درس
Clesson listOfLessons::getLessonByCode(unsigned int code)
{
  return lessons[(code - 1)];
}
#endif
<commit_msg>added a variable to keep the size of array (unsigned int index)<commit_after>/*
 * Class to make list of available lessons.
 * source available at (Github repo - MIT licence):
 * http://dstjrd.ir/s/cppx
 * https://github.com/mohsend/cpp-examples
 */

// این کلاس فقط برای این ساخته شده که لیستی از دروس ارایه شده را در اختیار کد اصلی بگذارد
// در یک مثال واقعی این اطلاعات در دیتابیس ذخیره میشوند و از آنجا لود میشوند. نه از یک فایل هدر
#ifndef LIST_OF_LESSONS_HPP
#define LIST_OF_LESSONS_HPP 1

#include <string>
#include "Clesson.hpp"

using namespace std;

class listOfLessons
{
  private:
    // یک آرایه از کلاس درس برای ذخیره واحد های ارایه شده
    Clesson lessons[14];
    unsigned int index;
  public:
    listOfLessons();
    Clesson getLessonByCode(unsigned int);
    void listAll();
};

// مقدار دهی به اجزای آرایه
listOfLessons::listOfLessons()
{
  index = 0;
  lessons[index++].setDetails("Persian literature", "Daemi", 2, 0, true);
  lessons[index++].setDetails("C++ fundamentals", "Pur ganji", 4, 0, true);
  lessons[index++].setDetails("maths 1", "Reza", 3, 0, true);
  lessons[index++].setDetails("maths 1", "Zia manesh", 3, 0, true);
  lessons[index++].setDetails("maths 2", "Reza", 3, 0, true);
  lessons[index++].setDetails("maths 2", "Zia manesh", 3, 0, true);
  lessons[index++].setDetails("physics 1", "Ghafari", 3, 0, true);
  lessons[index++].setDetails("physics 2", "Ghafari", 3, 0, true);
  lessons[index++].setDetails("phy lab 1", "", 1, 0, false);
  lessons[index++].setDetails("phy lab 2", "Salehi", 1, 0, false);
  lessons[index++].setDetails("history", "", 2, 0, true);
  lessons[index++].setDetails("object oriented programming", "Farhadi", 3, 0, true);
}

// لیست کردن تمام درس های ارایه شده.
void listOfLessons::listAll()
{
  for (unsigned int i = 0; i < index; i++)
  {
    string theory = (lessons[i].getTheory()) ? "Theory" : "Applied";
    cout << i + 1 << ") " << lessons[i].getName() << " by Prof. " << lessons[i].getLecturer() << " (" << lessons[i].getUnits()  << ' ' << theory << " units)" << endl;
  }
}

// متد ای برای گرفتن درس ارایه شده به صورت یک نمونه از کلاس درس با استفاده از کد درس
Clesson listOfLessons::getLessonByCode(unsigned int code)
{
  return lessons[(code - 1)];
}
#endif
<|endoftext|>


<commit_before>/*=============================================================================

    This file is part of FLINT.

    FLINT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    FLINT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with FLINT; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

=============================================================================*/
/******************************************************************************

    Copyright (C) 2013 Tom Bachmann

******************************************************************************/

#include<sstream>

#include "flintxx/expression.h"
#include "flintxx/tuple.h"

#include "flintxx/test/helpers.h"
#include "flintxx/test/myint.h"

using namespace flint;
using namespace mp;
using namespace traits;

void
test_initialization()
{
    myint a;
    tassert(a._data().payload == -1 && a._data().extra == 42);

    a._data().payload = 17;
    myint b = a;
    tassert(b._data().payload == 17);

    myint c(8);
    tassert(c._data().payload == 8 && c._data().extra == 2);

    myint d('a');
    tassert(d._data().payload == 'a' && d._data().extra == 3);

    myint e(c + c);
    tassert(e._data().payload == 16);
}

void
test_destruction()
{
    bool destroyed = false;
    {
        myint a;
        a._data().destroyed = &destroyed;
    }
    tassert(destroyed);
}

void
test_printing()
{
    std::ostringstream o;
    myint a(4);
    o << a;
    tassert(o.str() == "4");
}

void
test_assignment()
{
    myint a;
    myint b(43);
    a = b;
    tassert(a._data().payload == 43);
    tassert(a._data().extra == 4);

    a = 44l;
    tassert(a._data().payload == 44 && a._data().extra == 5);

    mylong c(0);
    c = a + b;
    tassert(c == 87l);
}

void
test_swap()
{
    myint a(2), b(3);
    swap(a, b);
    tassert(a == 3 && b == 2 && a._data().extra == 1234);
}

void
test_traits()
{
    typedef myint immediate_expression;
    typedef int immediate_nonexpression;
    typedef my_expression<
        operations::plus,
        make_tuple<const myint&, const myint&>::type
      > lazy_expression;

    tassert(is_expression<immediate_expression>::val == true);
    tassert(is_expression<immediate_nonexpression>::val == false);
    tassert(is_expression<lazy_expression>::val == true);

    tassert(is_immediate_expr<immediate_expression>::val == true);
    tassert(is_immediate_expr<immediate_nonexpression>::val == false);
    tassert(is_immediate_expr<lazy_expression>::val == false);

    tassert(is_immediate<immediate_expression>::val == true);
    tassert(is_immediate<immediate_nonexpression>::val == true);
    tassert(is_immediate<lazy_expression>::val == false);

    tassert(is_lazy_expr<immediate_expression>::val == false);
    tassert(is_lazy_expr<immediate_nonexpression>::val == false);
    tassert(is_lazy_expr<lazy_expression>::val == true);
    //tassert(is_lazy_expr<lazy_expression&>::val == false);
    tassert(is_lazy_expr<const immediate_expression&>::val == false);
}

void
test_equals()
{
    myint a(3);
    myint b(4);
    myint c(3);

    tassert(a != b);
    tassert(a == c);

    tassert(a == 3);
    tassert(3 == a);

    tassert(a != 4);
    tassert(4 != a);

    tassert((a + b) == (a + 4));
}

void
test_arithmetic()
{
    myint a(3);
    myint b(4);
    myint c(7);
    myint d(1);
    myint e(2);

    tassert((a + b).evaluate() == 7);
    tassert(a + b == c);
    tassert(a + b == 7);

    tassert(a - b == -1);
    tassert(a * b == 12);
    tassert(c / e == 3);
    tassert(c % e == 1);
    tassert(-a == -3);

    // Test arithmetic with immediates
    tassert(a + 4 == 7);
    tassert(4 + a == 7);
    tassert(a + 4l == 7);
    tassert(4u + a == 7);

    // Test composite arithmetic
    tassert((a + 1) + (b + 2) == 10);
    tassert((a + d) + (b + 2) == 10);
    tassert((a + d) + (b + e) == 10);
    tassert((3 + d) + (b + e) == 10);
    tassert((3 + d) + (4 + e) == 10);

    tassert(a + (b + c) == 14);
    tassert(3 + (b + c) == 14);
    tassert(3 + (4 + c) == 14);
    tassert(3 + (b + 7) == 14);
    tassert(a + (b + 7) == 14);

    tassert((b + c) + a == 14);
    tassert((b + c) + 3 == 14);
    tassert((4 + c) + 3== 14);
    tassert((b + 7) + 3== 14);
    tassert((b + 7) + a== 14);

    // test combining unary and binary arithmetic
    tassert(-(-a) == 3);
    tassert(-(a - b) == b - a);
    tassert(-((-a) + (-b)) == a + b);

    // Test mixed arithmetic
    mylong al(3l);
    mylong bl(4l);
    mylong cl(7l);

    tassert(al + bl == cl);
    tassert(al + bl == 7l);
    tassert(al + b  == 7l);
    tassert(a + bl  == 7l);
    tassert((a + bl) + cl  == 14l);
    tassert((a + b) + cl  == 14l);
    tassert((al + b) + c  == 14l);
    tassert(cl + (a + bl)  == 14l);
    tassert(cl + (a + b)  == 14l);
    tassert(c + (al + b)  == 14l);
    tassert((a + bl) + (cl + d) == 15l);
    tassert((a + bl) + (c + d) == 15l);

    tassert((a << 2) == 12);
    tassert(((a << 2) >> 2) == a);
}

void
test_conversion()
{
    myint a(4);
    mylong b(4l);
    tassert(typed_equals(a.to<int>(), 4));
    tassert(typed_equals(a.to<mylong>(), b));
    tassert(typed_equals((a + a).to<int>(), 8));
}

void
test_assignment_arith()
{
    myint a(1);
    myint b(2);
    a += b;
    tassert(a == 3 && b == 2);
    a += a*b;
    tassert(a == 9);
    a += 1;
    tassert(a == 10);
}

template<class T, class Expr>
bool is_subexpr(const Expr& e)
{
    return tools::has_subexpr<tools::equal_types_pred<T>, Expr>::val;
}
void
test_tools()
{
    typedef tools::equal_types_pred<myint> intpred;
    myint a(1);
    mylong b(2l);
    tassert(tools::find_subexpr<intpred>(a) == 1);
    tassert(tools::find_subexpr<intpred>(a + b) == 1);
    tassert(tools::find_subexpr_T<mylong>(a + b) == 2l);
    tassert(tools::find_subexpr<intpred>(b + (a + 2) + b) == 1);
    tassert(is_subexpr<myint>(a+b));
    tassert(!is_subexpr<mylong>(a+a));
}

void
test_temporaries()
{
    myint a(1);
#define T2 ((a + a) + (a + a))
#define T3 (T2 + T2)
    tassert(count_temporaries(T2) == 2);
    tassert(count_temporaries(T3) == 3);
    tassert(count_temporaries(T3 + T2) == 3);
    tassert(count_temporaries(T2 + T3) == 3);
}

void
test_references()
{
    mylong a(4);
    mylong_ref ar(a);
    mylong_cref acr(a);
    tassert(a == ar);
    tassert(a == acr);
    tassert(ar == acr);
    tassert(ar == 4l && acr == 4l);

    ar = 5l;
    tassert(a == 5l && acr == 5l && ar == 5l);

    mylong b(6);
    ar = b;
    tassert(a == b);

    mylong_cref bcr(b);
    b = 7l;
    ar = bcr;
    tassert(a == b);

    a = 4l;
    b = 5l;
    tassert(a + bcr == 9l);
    tassert(ar + bcr == 9l);
    a = acr + b;
    tassert(a == 9l);
    ar = acr + bcr;
    tassert(a == 14l);

    a = 4l;
    tassert((a + a) + bcr == 13l);
    tassert((acr + acr) + b == 13l);
    tassert(((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr)) == 40l);
    a = ((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr));
    tassert(a == 40l);
    a = 4l;
    ar = ((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr));
    tassert(a == 40l);
}

struct S { };
S operator+(const S& s, const S&) {return s;}
S operator-(const S&s) {return s;}
template<class T>
S operator*(const S& s, const T&) {return s;}
void
test_unrelated_overload()
{
    // Test a bug in our operator overloading logic which used to not allow
    // this to compile.
    S s;
    s = s + s;
    s = -s;
    s = s * (myint(5) + myint(5));
}

void
test_multiary()
{
    tassert(fourary_test(1, 2, 3, 4) == myint(1 + 2 + 3 + 4));
    tassert(fiveary_test(1, 2, 3, 4, 5u) == 1 + 2 + 3 + 4 + 5);
    tassert(sixary_test(1, 2, 3, 4, 5, 6) == 1 + 2 + 3 + 4 + 5 + 6);
    tassert(sevenary_test(1, 2, 3, 4, 5, 6, 7) == 1 + 2 + 3 + 4 + 5 + 6 + 7);
}

void
test_cstyle_io()
{
#if !defined (__WIN32) && !defined (__CYGWIN__)
    mylong c(17), d(0);
    FILE * f = std::fopen("expression_test", "w+");
    tassert(f);
    print(f, c);
    std::fprintf(f, "\n");
    print_pretty(f, c);
    std::fflush(f);
    std::fclose(f);

    f = std::fopen("expression_test", "r");
    tassert(read(f, d) > 0);
    tassert(d == c);
    d = 0l;
    std::fscanf(f, "\n");
    //tassert(read_pretty(f, d) > 0);
    //tassert(d == c);
    fclose(f);
    tassert(std::remove("expression_test") == 0);
#endif
}

int
main()
{
    std::cout << "expression....";

    test_traits();
    test_initialization();
    test_destruction();
    test_printing();
    test_assignment();
    test_swap();
    test_equals();
    test_arithmetic();
    test_conversion();
    test_assignment_arith();
    test_tools();
    test_temporaries();
    test_references();
    test_multiary();
    test_cstyle_io();

    test_unrelated_overload();

    std::cout << "PASS" << std::endl;

    // TODO test that certain things *don't* compile?

    return 0;
}
<commit_msg>Fixed a 0L.<commit_after>/*=============================================================================

    This file is part of FLINT.

    FLINT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    FLINT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with FLINT; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

=============================================================================*/
/******************************************************************************

    Copyright (C) 2013 Tom Bachmann

******************************************************************************/

#include<sstream>

#include "flintxx/expression.h"
#include "flintxx/tuple.h"

#include "flintxx/test/helpers.h"
#include "flintxx/test/myint.h"

using namespace flint;
using namespace mp;
using namespace traits;

void
test_initialization()
{
    myint a;
    tassert(a._data().payload == -1 && a._data().extra == 42);

    a._data().payload = 17;
    myint b = a;
    tassert(b._data().payload == 17);

    myint c(8);
    tassert(c._data().payload == 8 && c._data().extra == 2);

    myint d('a');
    tassert(d._data().payload == 'a' && d._data().extra == 3);

    myint e(c + c);
    tassert(e._data().payload == 16);
}

void
test_destruction()
{
    bool destroyed = false;
    {
        myint a;
        a._data().destroyed = &destroyed;
    }
    tassert(destroyed);
}

void
test_printing()
{
    std::ostringstream o;
    myint a(4);
    o << a;
    tassert(o.str() == "4");
}

void
test_assignment()
{
    myint a;
    myint b(43);
    a = b;
    tassert(a._data().payload == 43);
    tassert(a._data().extra == 4);

    a = 44l;
    tassert(a._data().payload == 44 && a._data().extra == 5);

    mylong c(0);
    c = a + b;
    tassert(c == 87l);
}

void
test_swap()
{
    myint a(2), b(3);
    swap(a, b);
    tassert(a == 3 && b == 2 && a._data().extra == 1234);
}

void
test_traits()
{
    typedef myint immediate_expression;
    typedef int immediate_nonexpression;
    typedef my_expression<
        operations::plus,
        make_tuple<const myint&, const myint&>::type
      > lazy_expression;

    tassert(is_expression<immediate_expression>::val == true);
    tassert(is_expression<immediate_nonexpression>::val == false);
    tassert(is_expression<lazy_expression>::val == true);

    tassert(is_immediate_expr<immediate_expression>::val == true);
    tassert(is_immediate_expr<immediate_nonexpression>::val == false);
    tassert(is_immediate_expr<lazy_expression>::val == false);

    tassert(is_immediate<immediate_expression>::val == true);
    tassert(is_immediate<immediate_nonexpression>::val == true);
    tassert(is_immediate<lazy_expression>::val == false);

    tassert(is_lazy_expr<immediate_expression>::val == false);
    tassert(is_lazy_expr<immediate_nonexpression>::val == false);
    tassert(is_lazy_expr<lazy_expression>::val == true);
    //tassert(is_lazy_expr<lazy_expression&>::val == false);
    tassert(is_lazy_expr<const immediate_expression&>::val == false);
}

void
test_equals()
{
    myint a(3);
    myint b(4);
    myint c(3);

    tassert(a != b);
    tassert(a == c);

    tassert(a == 3);
    tassert(3 == a);

    tassert(a != 4);
    tassert(4 != a);

    tassert((a + b) == (a + 4));
}

void
test_arithmetic()
{
    myint a(3);
    myint b(4);
    myint c(7);
    myint d(1);
    myint e(2);

    tassert((a + b).evaluate() == 7);
    tassert(a + b == c);
    tassert(a + b == 7);

    tassert(a - b == -1);
    tassert(a * b == 12);
    tassert(c / e == 3);
    tassert(c % e == 1);
    tassert(-a == -3);

    // Test arithmetic with immediates
    tassert(a + 4 == 7);
    tassert(4 + a == 7);
    tassert(a + 4l == 7);
    tassert(4u + a == 7);

    // Test composite arithmetic
    tassert((a + 1) + (b + 2) == 10);
    tassert((a + d) + (b + 2) == 10);
    tassert((a + d) + (b + e) == 10);
    tassert((3 + d) + (b + e) == 10);
    tassert((3 + d) + (4 + e) == 10);

    tassert(a + (b + c) == 14);
    tassert(3 + (b + c) == 14);
    tassert(3 + (4 + c) == 14);
    tassert(3 + (b + 7) == 14);
    tassert(a + (b + 7) == 14);

    tassert((b + c) + a == 14);
    tassert((b + c) + 3 == 14);
    tassert((4 + c) + 3== 14);
    tassert((b + 7) + 3== 14);
    tassert((b + 7) + a== 14);

    // test combining unary and binary arithmetic
    tassert(-(-a) == 3);
    tassert(-(a - b) == b - a);
    tassert(-((-a) + (-b)) == a + b);

    // Test mixed arithmetic
    mylong al(3l);
    mylong bl(4l);
    mylong cl(7l);

    tassert(al + bl == cl);
    tassert(al + bl == 7l);
    tassert(al + b  == 7l);
    tassert(a + bl  == 7l);
    tassert((a + bl) + cl  == 14l);
    tassert((a + b) + cl  == 14l);
    tassert((al + b) + c  == 14l);
    tassert(cl + (a + bl)  == 14l);
    tassert(cl + (a + b)  == 14l);
    tassert(c + (al + b)  == 14l);
    tassert((a + bl) + (cl + d) == 15l);
    tassert((a + bl) + (c + d) == 15l);

    tassert((a << 2) == 12);
    tassert(((a << 2) >> 2) == a);
}

void
test_conversion()
{
    myint a(4);
    mylong b(4l);
    tassert(typed_equals(a.to<int>(), 4));
    tassert(typed_equals(a.to<mylong>(), b));
    tassert(typed_equals((a + a).to<int>(), 8));
}

void
test_assignment_arith()
{
    myint a(1);
    myint b(2);
    a += b;
    tassert(a == 3 && b == 2);
    a += a*b;
    tassert(a == 9);
    a += 1;
    tassert(a == 10);
}

template<class T, class Expr>
bool is_subexpr(const Expr& e)
{
    return tools::has_subexpr<tools::equal_types_pred<T>, Expr>::val;
}
void
test_tools()
{
    typedef tools::equal_types_pred<myint> intpred;
    myint a(1);
    mylong b(2l);
    tassert(tools::find_subexpr<intpred>(a) == 1);
    tassert(tools::find_subexpr<intpred>(a + b) == 1);
    tassert(tools::find_subexpr_T<mylong>(a + b) == 2l);
    tassert(tools::find_subexpr<intpred>(b + (a + 2) + b) == 1);
    tassert(is_subexpr<myint>(a+b));
    tassert(!is_subexpr<mylong>(a+a));
}

void
test_temporaries()
{
    myint a(1);
#define T2 ((a + a) + (a + a))
#define T3 (T2 + T2)
    tassert(count_temporaries(T2) == 2);
    tassert(count_temporaries(T3) == 3);
    tassert(count_temporaries(T3 + T2) == 3);
    tassert(count_temporaries(T2 + T3) == 3);
}

void
test_references()
{
    mylong a(4);
    mylong_ref ar(a);
    mylong_cref acr(a);
    tassert(a == ar);
    tassert(a == acr);
    tassert(ar == acr);
    tassert(ar == 4l && acr == 4l);

    ar = 5l;
    tassert(a == 5l && acr == 5l && ar == 5l);

    mylong b(6);
    ar = b;
    tassert(a == b);

    mylong_cref bcr(b);
    b = 7l;
    ar = bcr;
    tassert(a == b);

    a = 4l;
    b = 5l;
    tassert(a + bcr == 9l);
    tassert(ar + bcr == 9l);
    a = acr + b;
    tassert(a == 9l);
    ar = acr + bcr;
    tassert(a == 14l);

    a = 4l;
    tassert((a + a) + bcr == 13l);
    tassert((acr + acr) + b == 13l);
    tassert(((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr)) == 40l);
    a = ((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr));
    tassert(a == 40l);
    a = 4l;
    ar = ((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr));
    tassert(a == 40l);
}

struct S { };
S operator+(const S& s, const S&) {return s;}
S operator-(const S&s) {return s;}
template<class T>
S operator*(const S& s, const T&) {return s;}
void
test_unrelated_overload()
{
    // Test a bug in our operator overloading logic which used to not allow
    // this to compile.
    S s;
    s = s + s;
    s = -s;
    s = s * (myint(5) + myint(5));
}

void
test_multiary()
{
    tassert(fourary_test(1, 2, 3, 4) == myint(1 + 2 + 3 + 4));
    tassert(fiveary_test(1, 2, 3, 4, 5u) == 1 + 2 + 3 + 4 + 5);
    tassert(sixary_test(1, 2, 3, 4, 5, 6) == 1 + 2 + 3 + 4 + 5 + 6);
    tassert(sevenary_test(1, 2, 3, 4, 5, 6, 7) == 1 + 2 + 3 + 4 + 5 + 6 + 7);
}

void
test_cstyle_io()
{
#if !defined (__WIN32) && !defined (__CYGWIN__)
    mylong c(17), d(0);
    FILE * f = std::fopen("expression_test", "w+");
    tassert(f);
    print(f, c);
    std::fprintf(f, "\n");
    print_pretty(f, c);
    std::fflush(f);
    std::fclose(f);

    f = std::fopen("expression_test", "r");
    tassert(read(f, d) > 0);
    tassert(d == c);
    d = WORD(0);
    std::fscanf(f, "\n");
    //tassert(read_pretty(f, d) > 0);
    //tassert(d == c);
    fclose(f);
    tassert(std::remove("expression_test") == 0);
#endif
}

int
main()
{
    std::cout << "expression....";

    test_traits();
    test_initialization();
    test_destruction();
    test_printing();
    test_assignment();
    test_swap();
    test_equals();
    test_arithmetic();
    test_conversion();
    test_assignment_arith();
    test_tools();
    test_temporaries();
    test_references();
    test_multiary();
    test_cstyle_io();

    test_unrelated_overload();

    std::cout << "PASS" << std::endl;

    // TODO test that certain things *don't* compile?

    return 0;
}
<|endoftext|>