<commit_before>#include "display.h"
#include "space.h"
#include "container.h"
#include "tree.h"
#include "application.h"
#include "window.h"
#include "helpers.h"

extern kwm_screen KWMScreen;
extern kwm_focus KWMFocus;
extern kwm_tiling KWMTiling;
extern kwm_thread KWMThread;
extern kwm_toggles KWMToggles;

void DisplayReconfigurationCallBack(CGDirectDisplayID Display, CGDisplayChangeSummaryFlags Flags, void *UserInfo)
{
    pthread_mutex_lock(&KWMThread.Lock);

    if (Flags & kCGDisplayAddFlag)
    {
        // Display has been added
        DEBUG("New display detected! DisplayID: " << Display << " Index: " << KWMScreen.ActiveCount)
        RefreshActiveDisplays();
    }
    else if (Flags & kCGDisplayRemoveFlag)
    {
        // Display has been removed
        if(CGDisplayIsAsleep(Display))
        {
            DEBUG("Display " << Display << " is asleep!")
        }
        else
        {
            DEBUG("Display has been removed! DisplayID: " << Display)
            std::map<int, space_info>::iterator It;
            for(It = KWMTiling.DisplayMap[Display].Space.begin(); It != KWMTiling.DisplayMap[Display].Space.end(); ++It)
                DestroyNodeTree(It->second.RootNode);

            if(KWMTiling.DisplayMap[Display].Identifier)
                CFRelease(KWMTiling.DisplayMap[Display].Identifier);

            KWMTiling.DisplayMap.erase(Display);
        }

        RefreshActiveDisplays();
    }

    pthread_mutex_unlock(&KWMThread.Lock);
}

screen_info CreateDefaultScreenInfo(int DisplayIndex, int ScreenIndex)
{
    CGRect DisplayRect = CGDisplayBounds(DisplayIndex);
    screen_info Screen;

    Screen.Identifier = NULL;
    Screen.ID = ScreenIndex;
    Screen.ActiveSpace = -1;
    Screen.OldWindowListCount = -1;

    Screen.X = DisplayRect.origin.x;
    Screen.Y = DisplayRect.origin.y;
    Screen.Width = DisplayRect.size.width;
    Screen.Height = DisplayRect.size.height;

    Screen.Settings.Offset = KWMScreen.DefaultOffset;
    Screen.Settings.Mode = SpaceModeDefault;
    return Screen;
}

void UpdateExistingScreenInfo(screen_info *Screen, int DisplayIndex, int ScreenIndex)
{
    CGRect DisplayRect = CGDisplayBounds(DisplayIndex);
    Screen->ID = ScreenIndex;

    Screen->X = DisplayRect.origin.x;
    Screen->Y = DisplayRect.origin.y;
    Screen->Width = DisplayRect.size.width;
    Screen->Height = DisplayRect.size.height;

    Screen->Settings.Offset = KWMScreen.DefaultOffset;
    Screen->Settings.Mode = SpaceModeDefault;
}

void GetActiveDisplays()
{
    KWMScreen.Displays = (CGDirectDisplayID*) malloc(sizeof(CGDirectDisplayID) * KWMScreen.MaxCount);
    CGGetActiveDisplayList(KWMScreen.MaxCount, KWMScreen.Displays, &KWMScreen.ActiveCount);
    for(std::size_t DisplayIndex = 0; DisplayIndex < KWMScreen.ActiveCount; ++DisplayIndex)
    {
        unsigned int DisplayID = KWMScreen.Displays[DisplayIndex];
        KWMTiling.DisplayMap[DisplayID] = CreateDefaultScreenInfo(DisplayID, DisplayIndex);;

        DEBUG("DisplayID " << DisplayID << " has index " << DisplayIndex)
    }

    KWMScreen.Current = GetDisplayOfMousePointer();
    KWMScreen.Current->ActiveSpace = GetActiveSpaceOfDisplay(KWMScreen.Current);
    ShouldActiveSpaceBeManaged();

    CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationCallBack, NULL);
}

void RefreshActiveDisplays()
{
    if(KWMScreen.Displays)
        free(KWMScreen.Displays);

    KWMScreen.Displays = (CGDirectDisplayID*) malloc(sizeof(CGDirectDisplayID) * KWMScreen.MaxCount);
    CGGetActiveDisplayList(KWMScreen.MaxCount, KWMScreen.Displays, &KWMScreen.ActiveCount);
    for(std::size_t DisplayIndex = 0; DisplayIndex < KWMScreen.ActiveCount; ++DisplayIndex)
    {
        unsigned int DisplayID = KWMScreen.Displays[DisplayIndex];
        std::map<unsigned int, screen_info>::iterator It = KWMTiling.DisplayMap.find(DisplayID);

        if(It != KWMTiling.DisplayMap.end())
            UpdateExistingScreenInfo(&KWMTiling.DisplayMap[DisplayID], DisplayID, DisplayIndex);
        else
            KWMTiling.DisplayMap[DisplayID] = CreateDefaultScreenInfo(DisplayID, DisplayIndex);

        DEBUG("DisplayID " << DisplayID << " has index " << DisplayIndex)
    }

    screen_info *NewScreen = GetDisplayOfMousePointer();
    if(NewScreen)
        GiveFocusToScreen(NewScreen->ID, NULL, false, true);
}

screen_info *GetDisplayFromScreenID(unsigned int ID)
{
    std::map<unsigned int, screen_info>::iterator It;
    for(It = KWMTiling.DisplayMap.begin(); It != KWMTiling.DisplayMap.end(); ++It)
    {
        screen_info *Screen = &It->second;
        if(Screen->ID == ID)
            return Screen;
    }

    return NULL;
}

screen_info *GetDisplayOfMousePointer()
{
    std::map<unsigned int, screen_info>::iterator It;
    for(It = KWMTiling.DisplayMap.begin(); It != KWMTiling.DisplayMap.end(); ++It)
    {
        CGPoint Cursor = GetCursorPos();
        screen_info *Screen = &It->second;
        if(Cursor.x >= Screen->X && Cursor.x <= Screen->X + Screen->Width &&
           Cursor.y >= Screen->Y && Cursor.y <= Screen->Y + Screen->Height)
               return Screen;
    }

    return NULL;
}

screen_info *GetDisplayOfWindow(window_info *Window)
{
    if(Window)
    {
        std::map<unsigned int, screen_info>::iterator It;
        for(It = KWMTiling.DisplayMap.begin(); It != KWMTiling.DisplayMap.end(); ++It)
        {
            screen_info *Screen = &It->second;
            if(Window->X >= Screen->X && Window->X <= Screen->X + Screen->Width &&
               Window->Y >= Screen->Y && Window->Y <= Screen->Y + Screen->Height)
                return Screen;
        }

        return GetDisplayOfMousePointer();
    }

    return NULL;
}

std::vector<window_info*> GetAllWindowsOnDisplay(int ScreenIndex)
{
    screen_info *Screen = GetDisplayFromScreenID(ScreenIndex);
    std::vector<window_info*> ScreenWindowLst;
    for(std::size_t WindowIndex = 0; WindowIndex < KWMTiling.WindowLst.size(); ++WindowIndex)
    {
        window_info *Window = &KWMTiling.WindowLst[WindowIndex];
        if(!IsApplicationFloating(&KWMTiling.WindowLst[WindowIndex]) &&
           !IsWindowFloating(KWMTiling.WindowLst[WindowIndex].WID, NULL))
        {
            if(Screen == GetDisplayOfWindow(Window))
                ScreenWindowLst.push_back(Window);
        }
    }

    return ScreenWindowLst;
}

void SetDefaultPaddingOfDisplay(container_offset Offset)
{
    KWMScreen.DefaultOffset.PaddingTop = Offset.PaddingTop;
    KWMScreen.DefaultOffset.PaddingBottom = Offset.PaddingBottom;
    KWMScreen.DefaultOffset.PaddingLeft = Offset.PaddingLeft;
    KWMScreen.DefaultOffset.PaddingRight = Offset.PaddingRight;
}

void SetDefaultGapOfDisplay(container_offset Offset)
{
    KWMScreen.DefaultOffset.VerticalGap = Offset.VerticalGap;
    KWMScreen.DefaultOffset.HorizontalGap = Offset.HorizontalGap;
}

void ChangePaddingOfDisplay(const std::string &Side, int Offset)
{
    screen_info *Screen = GetDisplayOfMousePointer();
    space_info *Space = GetActiveSpaceOfScreen(Screen);

    if(Side == "left")
    {
        if(Space->Settings.Offset.PaddingLeft + Offset >= 0)
            Space->Settings.Offset.PaddingLeft += Offset;
    }
    else if(Side == "right")
    {
        if(Space->Settings.Offset.PaddingRight + Offset >= 0)
            Space->Settings.Offset.PaddingRight += Offset;
    }
    else if(Side == "top")
    {
        if(Space->Settings.Offset.PaddingTop + Offset >= 0)
            Space->Settings.Offset.PaddingTop += Offset;
    }
    else if(Side == "bottom")
    {
        if(Space->Settings.Offset.PaddingBottom + Offset >= 0)
            Space->Settings.Offset.PaddingBottom += Offset;
    }

    if(Space->RootNode)
    {
        if(Space->Settings.Mode == SpaceModeBSP)
        {
            SetRootNodeContainer(Screen, Space->RootNode);
            CreateNodeContainers(Screen, Space->RootNode, true);
        }
        else if(Space->Settings.Mode == SpaceModeMonocle)
        {
            link_node *Link = Space->RootNode->List;
            while(Link)
            {
                SetLinkNodeContainer(Screen, Link);
                Link = Link->Next;
            }
        }

        ApplyTreeNodeContainer(Space->RootNode);
    }
}

void ChangeGapOfDisplay(const std::string &Side, int Offset)
{
    screen_info *Screen = GetDisplayOfMousePointer();
    space_info *Space = GetActiveSpaceOfScreen(Screen);

    if(Side == "vertical")
    {
        if(Space->Settings.Offset.VerticalGap + Offset >= 0)
            Space->Settings.Offset.VerticalGap += Offset;
    }
    else if(Side == "horizontal")
    {
        if(Space->Settings.Offset.HorizontalGap + Offset >= 0)
            Space->Settings.Offset.HorizontalGap += Offset;
    }

    if(Space->RootNode && Space->Settings.Mode == SpaceModeBSP)
    {
        CreateNodeContainers(Screen, Space->RootNode, true);
        ApplyTreeNodeContainer(Space->RootNode);
    }
}

int GetIndexOfNextScreen()
{
    return KWMScreen.Current->ID + 1 >= KWMScreen.ActiveCount ? 0 : KWMScreen.Current->ID + 1;
}

int GetIndexOfPrevScreen()
{
    return KWMScreen.Current->ID == 0 ? KWMScreen.ActiveCount - 1 : KWMScreen.Current->ID - 1;
}

void GiveFocusToScreen(unsigned int ScreenIndex, tree_node *FocusNode, bool Mouse, bool UpdateFocus)
{
    screen_info *Screen = GetDisplayFromScreenID(ScreenIndex);
    if(Screen && Screen != KWMScreen.Current)
    {
        KWMScreen.PrevSpace = KWMScreen.Current->ActiveSpace;
        KWMScreen.Current = Screen;

        Screen->ActiveSpace = GetActiveSpaceOfDisplay(Screen);
        ShouldActiveSpaceBeManaged();
        space_info *Space = GetActiveSpaceOfScreen(Screen);

        DEBUG("GiveFocusToScreen() " << ScreenIndex << \
              ": Space transition ended " << KWMScreen.PrevSpace << \
              " -> " << Screen->ActiveSpace)

        if(UpdateFocus)
        {
            if(Space->Initialized && FocusNode)
            {
                DEBUG("Populated Screen 'Window -f Focus'")

                UpdateActiveWindowList(Screen);
                FilterWindowList(Screen);
                SetWindowFocusByNode(FocusNode);
                MoveCursorToCenterOfFocusedWindow();
            }
            else if(Space->Initialized && Space->RootNode)
            {
                DEBUG("Populated Screen Key/Mouse Focus")

                UpdateActiveWindowList(Screen);
                FilterWindowList(Screen);

                bool WindowBelowCursor = IsAnyWindowBelowCursor();
                if(Mouse && !WindowBelowCursor)
                    ClearFocusedWindow();
                else if(Mouse && WindowBelowCursor)
                    FocusWindowBelowCursor();

                if(!Mouse)
                {
                    if(Space->FocusedWindowID == 0)
                    {
                        void *FocusNode = NULL;
                        GetFirstLeafNode(Space->RootNode, (void**)&FocusNode);
                        if(Space->Settings.Mode == SpaceModeBSP)
                            Space->FocusedWindowID = ((tree_node*)FocusNode)->WindowID;
                        else if(Space->Settings.Mode == SpaceModeMonocle)
                            Space->FocusedWindowID = ((link_node*)FocusNode)->WindowID;
                    }

                    FocusWindowByID(Space->FocusedWindowID);
                    MoveCursorToCenterOfFocusedWindow();
                }
            }
            else
            {
                if(!Space->Initialized ||
                        Space->Settings.Mode == SpaceModeFloating ||
                        !Space->RootNode)
                {
                    DEBUG("Uninitialized Screen")
                    ClearFocusedWindow();

                    if(Space->Settings.Mode != SpaceModeFloating)
                    {
                        if(!Mouse)
                            CGWarpMouseCursorPosition(CGPointMake(Screen->X + (Screen->Width / 2),
                                        Screen->Y + (Screen->Height / 2)));

                        if(!Space->RootNode)
                        {
                            CGPoint ClickPos = GetCursorPos();
                            CGEventRef ClickEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, ClickPos, kCGMouseButtonLeft);
                            CGEventSetFlags(ClickEvent, (CGEventFlags)0);
                            CGEventPost(kCGHIDEventTap, ClickEvent);
                            CFRelease(ClickEvent);

                            ClickEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, ClickPos, kCGMouseButtonLeft);
                            CGEventSetFlags(ClickEvent, (CGEventFlags)0);
                            CGEventPost(kCGHIDEventTap, ClickEvent);
                            CFRelease(ClickEvent);
                        }
                    }
                }
            }
        }
    }
}

void CaptureApplicationToScreen(int ScreenID, std::string Application)
{
    std::map<std::string, int>::iterator It = KWMTiling.CapturedAppLst.find(Application);
    if(It == KWMTiling.CapturedAppLst.end())
    {
        screen_info *Screen = GetDisplayFromScreenID(ScreenID);
        if(Screen)
        {
            KWMTiling.CapturedAppLst[Application] = ScreenID;
            DEBUG("CaptureApplicationToScreen() " << ScreenID << " " << Application)
        }
    }
}

void MoveWindowToDisplay(window_info *Window, int Shift, bool Relative, bool UpdateFocus)
{
    int NewScreenIndex = -1;

    if(Relative)
        NewScreenIndex = Shift == 1 ? GetIndexOfNextScreen() : GetIndexOfPrevScreen();
    else
        NewScreenIndex = Shift;

    screen_info *NewScreen = GetDisplayFromScreenID(NewScreenIndex);
    if(NewScreen)
        AddWindowToTreeOfUnfocusedMonitor(NewScreen, Window, UpdateFocus);
}

container_offset CreateDefaultScreenOffset()
{
    container_offset Offset = { 40, 20, 20, 20, 10, 10 };
    return Offset;
}

void UpdateActiveScreen()
{
    screen_info *Screen = GetDisplayOfMousePointer();
    if(KWMScreen.Current != Screen)
    {
        DEBUG("UpdateActiveScreen() Active Display Changed")

        ClearMarkedWindow();
        GiveFocusToScreen(Screen->ID, NULL, true, true);
    }
}

space_settings *GetSpaceSettingsForDisplay(unsigned int ScreenID)
{
    std::map<unsigned int, space_settings>::iterator It = KWMTiling.DisplaySettings.find(ScreenID);
    if(It != KWMTiling.DisplaySettings.end())
        return &It->second;
    else
        return NULL;
}
<commit_msg>added option to increase all paddings<commit_after>#include "display.h"
#include "space.h"
#include "container.h"
#include "tree.h"
#include "application.h"
#include "window.h"
#include "helpers.h"

extern kwm_screen KWMScreen;
extern kwm_focus KWMFocus;
extern kwm_tiling KWMTiling;
extern kwm_thread KWMThread;
extern kwm_toggles KWMToggles;

void DisplayReconfigurationCallBack(CGDirectDisplayID Display, CGDisplayChangeSummaryFlags Flags, void *UserInfo)
{
    pthread_mutex_lock(&KWMThread.Lock);

    if (Flags & kCGDisplayAddFlag)
    {
        // Display has been added
        DEBUG("New display detected! DisplayID: " << Display << " Index: " << KWMScreen.ActiveCount)
        RefreshActiveDisplays();
    }
    else if (Flags & kCGDisplayRemoveFlag)
    {
        // Display has been removed
        if(CGDisplayIsAsleep(Display))
        {
            DEBUG("Display " << Display << " is asleep!")
        }
        else
        {
            DEBUG("Display has been removed! DisplayID: " << Display)
            std::map<int, space_info>::iterator It;
            for(It = KWMTiling.DisplayMap[Display].Space.begin(); It != KWMTiling.DisplayMap[Display].Space.end(); ++It)
                DestroyNodeTree(It->second.RootNode);

            if(KWMTiling.DisplayMap[Display].Identifier)
                CFRelease(KWMTiling.DisplayMap[Display].Identifier);

            KWMTiling.DisplayMap.erase(Display);
        }

        RefreshActiveDisplays();
    }

    pthread_mutex_unlock(&KWMThread.Lock);
}

screen_info CreateDefaultScreenInfo(int DisplayIndex, int ScreenIndex)
{
    CGRect DisplayRect = CGDisplayBounds(DisplayIndex);
    screen_info Screen;

    Screen.Identifier = NULL;
    Screen.ID = ScreenIndex;
    Screen.ActiveSpace = -1;
    Screen.OldWindowListCount = -1;

    Screen.X = DisplayRect.origin.x;
    Screen.Y = DisplayRect.origin.y;
    Screen.Width = DisplayRect.size.width;
    Screen.Height = DisplayRect.size.height;

    Screen.Settings.Offset = KWMScreen.DefaultOffset;
    Screen.Settings.Mode = SpaceModeDefault;
    return Screen;
}

void UpdateExistingScreenInfo(screen_info *Screen, int DisplayIndex, int ScreenIndex)
{
    CGRect DisplayRect = CGDisplayBounds(DisplayIndex);
    Screen->ID = ScreenIndex;

    Screen->X = DisplayRect.origin.x;
    Screen->Y = DisplayRect.origin.y;
    Screen->Width = DisplayRect.size.width;
    Screen->Height = DisplayRect.size.height;

    Screen->Settings.Offset = KWMScreen.DefaultOffset;
    Screen->Settings.Mode = SpaceModeDefault;
}

void GetActiveDisplays()
{
    KWMScreen.Displays = (CGDirectDisplayID*) malloc(sizeof(CGDirectDisplayID) * KWMScreen.MaxCount);
    CGGetActiveDisplayList(KWMScreen.MaxCount, KWMScreen.Displays, &KWMScreen.ActiveCount);
    for(std::size_t DisplayIndex = 0; DisplayIndex < KWMScreen.ActiveCount; ++DisplayIndex)
    {
        unsigned int DisplayID = KWMScreen.Displays[DisplayIndex];
        KWMTiling.DisplayMap[DisplayID] = CreateDefaultScreenInfo(DisplayID, DisplayIndex);;

        DEBUG("DisplayID " << DisplayID << " has index " << DisplayIndex)
    }

    KWMScreen.Current = GetDisplayOfMousePointer();
    KWMScreen.Current->ActiveSpace = GetActiveSpaceOfDisplay(KWMScreen.Current);
    ShouldActiveSpaceBeManaged();

    CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationCallBack, NULL);
}

void RefreshActiveDisplays()
{
    if(KWMScreen.Displays)
        free(KWMScreen.Displays);

    KWMScreen.Displays = (CGDirectDisplayID*) malloc(sizeof(CGDirectDisplayID) * KWMScreen.MaxCount);
    CGGetActiveDisplayList(KWMScreen.MaxCount, KWMScreen.Displays, &KWMScreen.ActiveCount);
    for(std::size_t DisplayIndex = 0; DisplayIndex < KWMScreen.ActiveCount; ++DisplayIndex)
    {
        unsigned int DisplayID = KWMScreen.Displays[DisplayIndex];
        std::map<unsigned int, screen_info>::iterator It = KWMTiling.DisplayMap.find(DisplayID);

        if(It != KWMTiling.DisplayMap.end())
            UpdateExistingScreenInfo(&KWMTiling.DisplayMap[DisplayID], DisplayID, DisplayIndex);
        else
            KWMTiling.DisplayMap[DisplayID] = CreateDefaultScreenInfo(DisplayID, DisplayIndex);

        DEBUG("DisplayID " << DisplayID << " has index " << DisplayIndex)
    }

    screen_info *NewScreen = GetDisplayOfMousePointer();
    if(NewScreen)
        GiveFocusToScreen(NewScreen->ID, NULL, false, true);
}

screen_info *GetDisplayFromScreenID(unsigned int ID)
{
    std::map<unsigned int, screen_info>::iterator It;
    for(It = KWMTiling.DisplayMap.begin(); It != KWMTiling.DisplayMap.end(); ++It)
    {
        screen_info *Screen = &It->second;
        if(Screen->ID == ID)
            return Screen;
    }

    return NULL;
}

screen_info *GetDisplayOfMousePointer()
{
    std::map<unsigned int, screen_info>::iterator It;
    for(It = KWMTiling.DisplayMap.begin(); It != KWMTiling.DisplayMap.end(); ++It)
    {
        CGPoint Cursor = GetCursorPos();
        screen_info *Screen = &It->second;
        if(Cursor.x >= Screen->X && Cursor.x <= Screen->X + Screen->Width &&
           Cursor.y >= Screen->Y && Cursor.y <= Screen->Y + Screen->Height)
               return Screen;
    }

    return NULL;
}

screen_info *GetDisplayOfWindow(window_info *Window)
{
    if(Window)
    {
        std::map<unsigned int, screen_info>::iterator It;
        for(It = KWMTiling.DisplayMap.begin(); It != KWMTiling.DisplayMap.end(); ++It)
        {
            screen_info *Screen = &It->second;
            if(Window->X >= Screen->X && Window->X <= Screen->X + Screen->Width &&
               Window->Y >= Screen->Y && Window->Y <= Screen->Y + Screen->Height)
                return Screen;
        }

        return GetDisplayOfMousePointer();
    }

    return NULL;
}

std::vector<window_info*> GetAllWindowsOnDisplay(int ScreenIndex)
{
    screen_info *Screen = GetDisplayFromScreenID(ScreenIndex);
    std::vector<window_info*> ScreenWindowLst;
    for(std::size_t WindowIndex = 0; WindowIndex < KWMTiling.WindowLst.size(); ++WindowIndex)
    {
        window_info *Window = &KWMTiling.WindowLst[WindowIndex];
        if(!IsApplicationFloating(&KWMTiling.WindowLst[WindowIndex]) &&
           !IsWindowFloating(KWMTiling.WindowLst[WindowIndex].WID, NULL))
        {
            if(Screen == GetDisplayOfWindow(Window))
                ScreenWindowLst.push_back(Window);
        }
    }

    return ScreenWindowLst;
}

void SetDefaultPaddingOfDisplay(container_offset Offset)
{
    KWMScreen.DefaultOffset.PaddingTop = Offset.PaddingTop;
    KWMScreen.DefaultOffset.PaddingBottom = Offset.PaddingBottom;
    KWMScreen.DefaultOffset.PaddingLeft = Offset.PaddingLeft;
    KWMScreen.DefaultOffset.PaddingRight = Offset.PaddingRight;
}

void SetDefaultGapOfDisplay(container_offset Offset)
{
    KWMScreen.DefaultOffset.VerticalGap = Offset.VerticalGap;
    KWMScreen.DefaultOffset.HorizontalGap = Offset.HorizontalGap;
}

void ChangePaddingOfDisplay(const std::string &Side, int Offset)
{
    screen_info *Screen = GetDisplayOfMousePointer();
    space_info *Space = GetActiveSpaceOfScreen(Screen);

    if(Side == "all")
    {
        if(Space->Settings.Offset.PaddingLeft + Offset >= 0)
            Space->Settings.Offset.PaddingLeft += Offset;

        if(Space->Settings.Offset.PaddingRight + Offset >= 0)
            Space->Settings.Offset.PaddingRight += Offset;

        if(Space->Settings.Offset.PaddingTop + Offset >= 0)
            Space->Settings.Offset.PaddingTop += Offset;

        if(Space->Settings.Offset.PaddingBottom + Offset >= 0)
            Space->Settings.Offset.PaddingBottom += Offset;
    }
    else if(Side == "left")
    {
        if(Space->Settings.Offset.PaddingLeft + Offset >= 0)
            Space->Settings.Offset.PaddingLeft += Offset;
    }
    else if(Side == "right")
    {
        if(Space->Settings.Offset.PaddingRight + Offset >= 0)
            Space->Settings.Offset.PaddingRight += Offset;
    }
    else if(Side == "top")
    {
        if(Space->Settings.Offset.PaddingTop + Offset >= 0)
            Space->Settings.Offset.PaddingTop += Offset;
    }
    else if(Side == "bottom")
    {
        if(Space->Settings.Offset.PaddingBottom + Offset >= 0)
            Space->Settings.Offset.PaddingBottom += Offset;
    }

    if(Space->RootNode)
    {
        if(Space->Settings.Mode == SpaceModeBSP)
        {
            SetRootNodeContainer(Screen, Space->RootNode);
            CreateNodeContainers(Screen, Space->RootNode, true);
        }
        else if(Space->Settings.Mode == SpaceModeMonocle)
        {
            link_node *Link = Space->RootNode->List;
            while(Link)
            {
                SetLinkNodeContainer(Screen, Link);
                Link = Link->Next;
            }
        }

        ApplyTreeNodeContainer(Space->RootNode);
    }
}

void ChangeGapOfDisplay(const std::string &Side, int Offset)
{
    screen_info *Screen = GetDisplayOfMousePointer();
    space_info *Space = GetActiveSpaceOfScreen(Screen);

    if(Side == "all")
    {
        if(Space->Settings.Offset.VerticalGap + Offset >= 0)
            Space->Settings.Offset.VerticalGap += Offset;

        if(Space->Settings.Offset.HorizontalGap + Offset >= 0)
            Space->Settings.Offset.HorizontalGap += Offset;
    }
    else if(Side == "vertical")
    {
        if(Space->Settings.Offset.VerticalGap + Offset >= 0)
            Space->Settings.Offset.VerticalGap += Offset;
    }
    else if(Side == "horizontal")
    {
        if(Space->Settings.Offset.HorizontalGap + Offset >= 0)
            Space->Settings.Offset.HorizontalGap += Offset;
    }

    if(Space->RootNode && Space->Settings.Mode == SpaceModeBSP)
    {
        CreateNodeContainers(Screen, Space->RootNode, true);
        ApplyTreeNodeContainer(Space->RootNode);
    }
}

int GetIndexOfNextScreen()
{
    return KWMScreen.Current->ID + 1 >= KWMScreen.ActiveCount ? 0 : KWMScreen.Current->ID + 1;
}

int GetIndexOfPrevScreen()
{
    return KWMScreen.Current->ID == 0 ? KWMScreen.ActiveCount - 1 : KWMScreen.Current->ID - 1;
}

void GiveFocusToScreen(unsigned int ScreenIndex, tree_node *FocusNode, bool Mouse, bool UpdateFocus)
{
    screen_info *Screen = GetDisplayFromScreenID(ScreenIndex);
    if(Screen && Screen != KWMScreen.Current)
    {
        KWMScreen.PrevSpace = KWMScreen.Current->ActiveSpace;
        KWMScreen.Current = Screen;

        Screen->ActiveSpace = GetActiveSpaceOfDisplay(Screen);
        ShouldActiveSpaceBeManaged();
        space_info *Space = GetActiveSpaceOfScreen(Screen);

        DEBUG("GiveFocusToScreen() " << ScreenIndex << \
              ": Space transition ended " << KWMScreen.PrevSpace << \
              " -> " << Screen->ActiveSpace)

        if(UpdateFocus)
        {
            if(Space->Initialized && FocusNode)
            {
                DEBUG("Populated Screen 'Window -f Focus'")

                UpdateActiveWindowList(Screen);
                FilterWindowList(Screen);
                SetWindowFocusByNode(FocusNode);
                MoveCursorToCenterOfFocusedWindow();
            }
            else if(Space->Initialized && Space->RootNode)
            {
                DEBUG("Populated Screen Key/Mouse Focus")

                UpdateActiveWindowList(Screen);
                FilterWindowList(Screen);

                bool WindowBelowCursor = IsAnyWindowBelowCursor();
                if(Mouse && !WindowBelowCursor)
                    ClearFocusedWindow();
                else if(Mouse && WindowBelowCursor)
                    FocusWindowBelowCursor();

                if(!Mouse)
                {
                    if(Space->FocusedWindowID == 0)
                    {
                        void *FocusNode = NULL;
                        GetFirstLeafNode(Space->RootNode, (void**)&FocusNode);
                        if(Space->Settings.Mode == SpaceModeBSP)
                            Space->FocusedWindowID = ((tree_node*)FocusNode)->WindowID;
                        else if(Space->Settings.Mode == SpaceModeMonocle)
                            Space->FocusedWindowID = ((link_node*)FocusNode)->WindowID;
                    }

                    FocusWindowByID(Space->FocusedWindowID);
                    MoveCursorToCenterOfFocusedWindow();
                }
            }
            else
            {
                if(!Space->Initialized ||
                        Space->Settings.Mode == SpaceModeFloating ||
                        !Space->RootNode)
                {
                    DEBUG("Uninitialized Screen")
                    ClearFocusedWindow();

                    if(Space->Settings.Mode != SpaceModeFloating)
                    {
                        if(!Mouse)
                            CGWarpMouseCursorPosition(CGPointMake(Screen->X + (Screen->Width / 2),
                                        Screen->Y + (Screen->Height / 2)));

                        if(!Space->RootNode)
                        {
                            CGPoint ClickPos = GetCursorPos();
                            CGEventRef ClickEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, ClickPos, kCGMouseButtonLeft);
                            CGEventSetFlags(ClickEvent, (CGEventFlags)0);
                            CGEventPost(kCGHIDEventTap, ClickEvent);
                            CFRelease(ClickEvent);

                            ClickEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, ClickPos, kCGMouseButtonLeft);
                            CGEventSetFlags(ClickEvent, (CGEventFlags)0);
                            CGEventPost(kCGHIDEventTap, ClickEvent);
                            CFRelease(ClickEvent);
                        }
                    }
                }
            }
        }
    }
}

void CaptureApplicationToScreen(int ScreenID, std::string Application)
{
    std::map<std::string, int>::iterator It = KWMTiling.CapturedAppLst.find(Application);
    if(It == KWMTiling.CapturedAppLst.end())
    {
        screen_info *Screen = GetDisplayFromScreenID(ScreenID);
        if(Screen)
        {
            KWMTiling.CapturedAppLst[Application] = ScreenID;
            DEBUG("CaptureApplicationToScreen() " << ScreenID << " " << Application)
        }
    }
}

void MoveWindowToDisplay(window_info *Window, int Shift, bool Relative, bool UpdateFocus)
{
    int NewScreenIndex = -1;

    if(Relative)
        NewScreenIndex = Shift == 1 ? GetIndexOfNextScreen() : GetIndexOfPrevScreen();
    else
        NewScreenIndex = Shift;

    screen_info *NewScreen = GetDisplayFromScreenID(NewScreenIndex);
    if(NewScreen)
        AddWindowToTreeOfUnfocusedMonitor(NewScreen, Window, UpdateFocus);
}

container_offset CreateDefaultScreenOffset()
{
    container_offset Offset = { 40, 20, 20, 20, 10, 10 };
    return Offset;
}

void UpdateActiveScreen()
{
    screen_info *Screen = GetDisplayOfMousePointer();
    if(KWMScreen.Current != Screen)
    {
        DEBUG("UpdateActiveScreen() Active Display Changed")

        ClearMarkedWindow();
        GiveFocusToScreen(Screen->ID, NULL, true, true);
    }
}

space_settings *GetSpaceSettingsForDisplay(unsigned int ScreenID)
{
    std::map<unsigned int, space_settings>::iterator It = KWMTiling.DisplaySettings.find(ScreenID);
    if(It != KWMTiling.DisplaySettings.end())
        return &It->second;
    else
        return NULL;
}
<|endoftext|>


<commit_before>/**
 * @file hrectbound_impl.hpp
 *
 * Implementation of hyper-rectangle bound policy class.
 * Template parameter Power is the metric to use; use 2 for Euclidean (L2).
 *
 * @experimental
 */
#ifndef __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
#define __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP

#include <math.h>

// In case it has not been included yet.
#include "hrectbound.hpp"

namespace mlpack {
namespace bound {

/**
 * Empty constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound() :
    dim(0),
    bounds(NULL)
{ /* Nothing to do. */ }

/**
 * Initializes to specified dimensionality with each dimension the empty
 * set.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const size_t dimension) :
    dim(dimension),
    bounds(new math::Range[dim])
{ /* Nothing to do. */ }

/***
 * Copy constructor necessary to prevent memory leaks.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const HRectBound& other) :
    dim(other.Dim()),
    bounds(new math::Range[dim])
{
  // Copy other bounds over.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];
}

/***
 * Same as the copy constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator=(
    const HRectBound& other)
{
  if (dim != other.Dim())
  {
    // Reallocation is necessary.
    if (bounds)
      delete[] bounds;

    dim = other.Dim();
    bounds = new math::Range[dim];
  }

  // Now copy each of the bound values.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];

  return *this;
}

/**
 * Destructor: clean up memory.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::~HRectBound()
{
  if (bounds)
    delete[] bounds;
}

/**
 * Resets all dimensions to the empty set.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Clear()
{
  for (size_t i = 0; i < dim; i++)
    bounds[i] = math::Range();
}

/**
 * Gets the range for a particular dimension.
 */
template<int Power, bool TakeRoot>
inline const math::Range& HRectBound<Power, TakeRoot>::operator[](
    const size_t i) const
{
  return bounds[i];
}

/**
 * Sets the range for the given dimension.
 */
template<int Power, bool TakeRoot>
inline math::Range& HRectBound<Power, TakeRoot>::operator[](const size_t i)
{
  return bounds[i];
}

/***
 * Calculates the centroid of the range, placing it into the given vector.
 *
 * @param centroid Vector which the centroid will be written to.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Centroid(arma::vec& centroid) const
{
  // Set size correctly if necessary.
  if (!(centroid.n_elem == dim))
    centroid.set_size(dim);

  for (size_t i = 0; i < dim; i++)
    centroid(i) = bounds[i].Mid();
}

/**
 * Calculates minimum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MinDistance(const VecType& point) const
{
  Log::Assert(point.n_elem == dim);

  double sum = 0;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = bounds[d].Lo() - point[d];
    higher = point[d] - bounds[d].Hi();

    // Since only one of 'lower' or 'higher' is negative, if we add each's
    // absolute value to itself and then sum those two, our result is the
    // nonnegative half of the equation times two; then we raise to power Power.
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);
  }

  // Now take the Power'th root (but make sure our result is squared if it needs
  // to be); then cancel out the constant of 2 (which may have been squared now)
  // that was introduced earlier.  The compiler should optimize out the if
  // statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates minimum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MinDistance(const HRectBound& other) const
{
  Log::Assert(dim == other.dim);

  double sum = 0;
  const math::Range* mbound = bounds;
  const math::Range* obound = other.bounds;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = obound->Lo() - mbound->Hi();
    higher = mbound->Lo() - obound->Hi();
    // We invoke the following:
    //   x + fabs(x) = max(x * 2, 0)
    //   (x * 2)^2 / 4 = x^2
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);

    // Move bound pointers.
    mbound++;
    obound++;
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MaxDistance(const VecType& point) const
{
  double sum = 0;

  Log::Assert(point.n_elem == dim);

  for (size_t d = 0; d < dim; d++)
  {
    double v = std::max(fabs(point[d] - bounds[d].Lo()),
        fabs(bounds[d].Hi() - point[d]));
    sum += pow(v, (double) Power);
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Computes maximum distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MaxDistance(const HRectBound& other) const
{
  double sum = 0;

  Log::Assert(dim == other.dim);

  double v;
  for (size_t d = 0; d < dim; d++)
  {
    v = std::max(fabs(other.bounds[d].Hi() - bounds[d].Lo()),
        fabs(bounds[d].Hi() - other.bounds[d].Lo()));
    sum += pow(v, (double) Power); // v is non-negative.
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Calculates minimum and maximum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(const HRectBound& other)
    const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(dim == other.dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = other.bounds[d].Lo() - bounds[d].Hi();
    v2 = bounds[d].Lo() - other.bounds[d].Hi();
    // One of v1 or v2 is negative.
    if (v1 >= v2)
    {
      vHi = -v2; // Make it nonnegative.
      vLo = (v1 > 0) ? v1 : 0; // Force to be 0 if negative.
    }
    else
    {
      vHi = -v1; // Make it nonnegative.
      vLo = (v2 > 0) ? v2 : 0; // Force to be 0 if negative.
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Calculates minimum and maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(const VecType& point)
    const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(point.n_elem == dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = bounds[d].Lo() - point[d]; // Negative if point[d] > lo.
    v2 = point[d] - bounds[d].Hi(); // Negative if point[d] < hi.
    // One of v1 or v2 (or both) is negative.
    if (v1 >= 0) // point[d] <= bounds_[d].Lo().
    {
      vHi = -v2; // v2 will be larger but must be negated.
      vLo = v1;
    }
    else // point[d] is between lo and hi, or greater than hi.
    {
      if (v2 >= 0)
      {
        vHi = -v1; // v1 will be larger, but must be negated.
        vLo = v2;
      }
      else
      {
        vHi = -std::min(v1, v2); // Both are negative, but we need the larger.
        vLo = 0;
      }
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Expands this region to include a new point.
 */
template<int Power, bool TakeRoot>
template<typename MatType>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const MatType& data)
{
  Log::Assert(data.n_rows == dim);

  arma::vec mins(min(data, 1));
  arma::vec maxs(max(data, 1));

  for (size_t i = 0; i < dim; i++)
    bounds[i] |= math::Range(mins[i], maxs[i]);

  return *this;
}

/**
 * Expands this region to encompass another bound.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const HRectBound& other)
{
  assert(other.dim == dim);

  for (size_t i = 0; i < dim; i++)
    bounds[i] |= other.bounds[i];

  return *this;
}

/**
 * Determines if a point is within this bound.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
bool HRectBound<Power, TakeRoot>::Contains(const VecType& point) const
{
  for (size_t i = 0; i < point.n_elem; i++)
  {
    if (!bounds[i].Contains(point(i)))
      return false;
  }

  return true;
}

/**
 * Returns a string representation of this object.
 */
template<int Power, bool TakeRoot>
std::string HRectBound<Power, TakeRoot>::ToString() const
{
  std::ostringstream convert;
  convert << "HRectBound [" << this << "]" << std::endl;
  convert << "dim: " << dim << std::endl;
  convert << "bounds: " << bounds->ToString() << std::endl;
  return convert.str();
}

}; // namespace bound
}; // namespace mlpack

#endif // __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
<commit_msg>Fix unsafe code in HRectBound; bounds can be NULL.<commit_after>/**
 * @file hrectbound_impl.hpp
 *
 * Implementation of hyper-rectangle bound policy class.
 * Template parameter Power is the metric to use; use 2 for Euclidean (L2).
 *
 * @experimental
 */
#ifndef __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
#define __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP

#include <math.h>

// In case it has not been included yet.
#include "hrectbound.hpp"

namespace mlpack {
namespace bound {

/**
 * Empty constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound() :
    dim(0),
    bounds(NULL)
{ /* Nothing to do. */ }

/**
 * Initializes to specified dimensionality with each dimension the empty
 * set.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const size_t dimension) :
    dim(dimension),
    bounds(new math::Range[dim])
{ /* Nothing to do. */ }

/***
 * Copy constructor necessary to prevent memory leaks.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const HRectBound& other) :
    dim(other.Dim()),
    bounds(new math::Range[dim])
{
  // Copy other bounds over.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];
}

/***
 * Same as the copy constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator=(
    const HRectBound& other)
{
  if (dim != other.Dim())
  {
    // Reallocation is necessary.
    if (bounds)
      delete[] bounds;

    dim = other.Dim();
    bounds = new math::Range[dim];
  }

  // Now copy each of the bound values.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];

  return *this;
}

/**
 * Destructor: clean up memory.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::~HRectBound()
{
  if (bounds)
    delete[] bounds;
}

/**
 * Resets all dimensions to the empty set.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Clear()
{
  for (size_t i = 0; i < dim; i++)
    bounds[i] = math::Range();
}

/**
 * Gets the range for a particular dimension.
 */
template<int Power, bool TakeRoot>
inline const math::Range& HRectBound<Power, TakeRoot>::operator[](
    const size_t i) const
{
  return bounds[i];
}

/**
 * Sets the range for the given dimension.
 */
template<int Power, bool TakeRoot>
inline math::Range& HRectBound<Power, TakeRoot>::operator[](const size_t i)
{
  return bounds[i];
}

/***
 * Calculates the centroid of the range, placing it into the given vector.
 *
 * @param centroid Vector which the centroid will be written to.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Centroid(arma::vec& centroid) const
{
  // Set size correctly if necessary.
  if (!(centroid.n_elem == dim))
    centroid.set_size(dim);

  for (size_t i = 0; i < dim; i++)
    centroid(i) = bounds[i].Mid();
}

/**
 * Calculates minimum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MinDistance(const VecType& point) const
{
  Log::Assert(point.n_elem == dim);

  double sum = 0;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = bounds[d].Lo() - point[d];
    higher = point[d] - bounds[d].Hi();

    // Since only one of 'lower' or 'higher' is negative, if we add each's
    // absolute value to itself and then sum those two, our result is the
    // nonnegative half of the equation times two; then we raise to power Power.
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);
  }

  // Now take the Power'th root (but make sure our result is squared if it needs
  // to be); then cancel out the constant of 2 (which may have been squared now)
  // that was introduced earlier.  The compiler should optimize out the if
  // statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates minimum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MinDistance(const HRectBound& other) const
{
  Log::Assert(dim == other.dim);

  double sum = 0;
  const math::Range* mbound = bounds;
  const math::Range* obound = other.bounds;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = obound->Lo() - mbound->Hi();
    higher = mbound->Lo() - obound->Hi();
    // We invoke the following:
    //   x + fabs(x) = max(x * 2, 0)
    //   (x * 2)^2 / 4 = x^2
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);

    // Move bound pointers.
    mbound++;
    obound++;
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MaxDistance(const VecType& point) const
{
  double sum = 0;

  Log::Assert(point.n_elem == dim);

  for (size_t d = 0; d < dim; d++)
  {
    double v = std::max(fabs(point[d] - bounds[d].Lo()),
        fabs(bounds[d].Hi() - point[d]));
    sum += pow(v, (double) Power);
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Computes maximum distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MaxDistance(const HRectBound& other) const
{
  double sum = 0;

  Log::Assert(dim == other.dim);

  double v;
  for (size_t d = 0; d < dim; d++)
  {
    v = std::max(fabs(other.bounds[d].Hi() - bounds[d].Lo()),
        fabs(bounds[d].Hi() - other.bounds[d].Lo()));
    sum += pow(v, (double) Power); // v is non-negative.
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Calculates minimum and maximum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(const HRectBound& other)
    const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(dim == other.dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = other.bounds[d].Lo() - bounds[d].Hi();
    v2 = bounds[d].Lo() - other.bounds[d].Hi();
    // One of v1 or v2 is negative.
    if (v1 >= v2)
    {
      vHi = -v2; // Make it nonnegative.
      vLo = (v1 > 0) ? v1 : 0; // Force to be 0 if negative.
    }
    else
    {
      vHi = -v1; // Make it nonnegative.
      vLo = (v2 > 0) ? v2 : 0; // Force to be 0 if negative.
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Calculates minimum and maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(const VecType& point)
    const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(point.n_elem == dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = bounds[d].Lo() - point[d]; // Negative if point[d] > lo.
    v2 = point[d] - bounds[d].Hi(); // Negative if point[d] < hi.
    // One of v1 or v2 (or both) is negative.
    if (v1 >= 0) // point[d] <= bounds_[d].Lo().
    {
      vHi = -v2; // v2 will be larger but must be negated.
      vLo = v1;
    }
    else // point[d] is between lo and hi, or greater than hi.
    {
      if (v2 >= 0)
      {
        vHi = -v1; // v1 will be larger, but must be negated.
        vLo = v2;
      }
      else
      {
        vHi = -std::min(v1, v2); // Both are negative, but we need the larger.
        vLo = 0;
      }
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Expands this region to include a new point.
 */
template<int Power, bool TakeRoot>
template<typename MatType>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const MatType& data)
{
  Log::Assert(data.n_rows == dim);

  arma::vec mins(min(data, 1));
  arma::vec maxs(max(data, 1));

  for (size_t i = 0; i < dim; i++)
    bounds[i] |= math::Range(mins[i], maxs[i]);

  return *this;
}

/**
 * Expands this region to encompass another bound.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const HRectBound& other)
{
  assert(other.dim == dim);

  for (size_t i = 0; i < dim; i++)
    bounds[i] |= other.bounds[i];

  return *this;
}

/**
 * Determines if a point is within this bound.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
bool HRectBound<Power, TakeRoot>::Contains(const VecType& point) const
{
  for (size_t i = 0; i < point.n_elem; i++)
  {
    if (!bounds[i].Contains(point(i)))
      return false;
  }

  return true;
}

/**
 * Returns a string representation of this object.
 */
template<int Power, bool TakeRoot>
std::string HRectBound<Power, TakeRoot>::ToString() const
{
  std::ostringstream convert;
  convert << "HRectBound [" << this << "]" << std::endl;
  convert << "dim: " << dim << std::endl;
  convert << "bounds: " << std::endl;
  for (size_t i = 0; i < dim; ++i)
    convert << util::Indent(bounds[i].ToString()) << std::endl;

  return convert.str();
}

}; // namespace bound
}; // namespace mlpack

#endif // __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "SubProblem.h"
#include "Factory.h"
#include "MooseMesh.h"
#include "Conversion.h"
#include "Function.h"
#include "MooseApp.h"
#include "MooseVariableFEImpl.h"
#include "MooseArray.h"

template <>
InputParameters
validParams<SubProblem>()
{
  InputParameters params = validParams<Problem>();
  return params;
}

namespace
{
/**
 * Templated helper that returns either the any block or any boundary ID depending on the template
 * parameter.
 */
template <typename T>
T getAnyID();
}

// SubProblem /////
SubProblem::SubProblem(const InputParameters & parameters)
  : Problem(parameters),
    _factory(_app.getFactory()),
    _nonlocal_cm(),
    _requires_nonlocal_coupling(false),
    _rz_coord_axis(1), // default to RZ rotation around y-axis
    _currently_computing_jacobian(false),
    _computing_nonlinear_residual(false)
{
  unsigned int n_threads = libMesh::n_threads();
  _active_elemental_moose_variables.resize(n_threads);
  _has_active_elemental_moose_variables.resize(n_threads);
  _active_material_property_ids.resize(n_threads);
}

SubProblem::~SubProblem() {}

TagID
SubProblem::addVectorTag(TagName tag_name)
{
  if (_vector_tag_name_to_tag_id.find(tag_name) == _vector_tag_name_to_tag_id.end())
  {
    auto tag_id = _vector_tag_name_to_tag_id.size();

    _vector_tag_name_to_tag_id[tag_name] = tag_id;

    _vector_tag_id_to_tag_name[tag_id] = tag_name;
  }

  return _vector_tag_name_to_tag_id.at(tag_name);
}

TagID
SubProblem::getVectorTag(TagName tag_name)
{
  return _vector_tag_name_to_tag_id.at(tag_name);
}

TagName
SubProblem::vectorTagName(TagID tag)
{
  return _vector_tag_id_to_tag_name[tag];
}

TagID
SubProblem::addMatrixTag(TagName tag_name)
{
  if (_matrix_tag_name_to_tag_id.find(tag_name) == _matrix_tag_name_to_tag_id.end())
  {
    auto tag_id = _matrix_tag_name_to_tag_id.size();

    _matrix_tag_name_to_tag_id[tag_name] = tag_id;

    _matrix_tag_id_to_tag_name[tag_id] = tag_name;
  }

  return _matrix_tag_name_to_tag_id.at(tag_name);
}

TagID
SubProblem::getMatrixTag(TagName tag_name)
{
  return _matrix_tag_name_to_tag_id.at(tag_name);
}

TagName
SubProblem::matrixTagName(TagID tag)
{
  return _matrix_tag_id_to_tag_name[tag];
}

void
SubProblem::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
                                             THREAD_ID tid)
{
  if (!moose_vars.empty())
  {
    _has_active_elemental_moose_variables[tid] = 1;
    _active_elemental_moose_variables[tid] = moose_vars;
  }
}

const std::set<MooseVariableFEBase *> &
SubProblem::getActiveElementalMooseVariables(THREAD_ID tid) const
{
  return _active_elemental_moose_variables[tid];
}

bool
SubProblem::hasActiveElementalMooseVariables(THREAD_ID tid) const
{
  return _has_active_elemental_moose_variables[tid];
}

void
SubProblem::clearActiveElementalMooseVariables(THREAD_ID tid)
{
  _has_active_elemental_moose_variables[tid] = 0;
  _active_elemental_moose_variables[tid].clear();
}

void
SubProblem::setActiveMaterialProperties(const std::set<unsigned int> & mat_prop_ids, THREAD_ID tid)
{
  if (!mat_prop_ids.empty())
    _active_material_property_ids[tid] = mat_prop_ids;
}

const std::set<unsigned int> &
SubProblem::getActiveMaterialProperties(THREAD_ID tid) const
{
  return _active_material_property_ids[tid];
}

bool
SubProblem::hasActiveMaterialProperties(THREAD_ID tid) const
{
  return !_active_material_property_ids[tid].empty();
}

void
SubProblem::clearActiveMaterialProperties(THREAD_ID tid)
{
  _active_material_property_ids[tid].clear();
}

std::set<SubdomainID>
SubProblem::getMaterialPropertyBlocks(const std::string & prop_name)
{
  std::set<SubdomainID> blocks;

  for (const auto & it : _map_block_material_props)
  {
    const std::set<std::string> & prop_names = it.second;
    std::set<std::string>::iterator name_it = prop_names.find(prop_name);
    if (name_it != prop_names.end())
      blocks.insert(it.first);
  }

  return blocks;
}

std::vector<SubdomainName>
SubProblem::getMaterialPropertyBlockNames(const std::string & prop_name)
{
  std::set<SubdomainID> blocks = getMaterialPropertyBlocks(prop_name);
  std::vector<SubdomainName> block_names;
  block_names.reserve(blocks.size());
  for (const auto & block_id : blocks)
  {
    SubdomainName name;
    if (block_id == Moose::ANY_BLOCK_ID)
      name = "ANY_BLOCK_ID";
    else
    {
      name = mesh().getMesh().subdomain_name(block_id);
      if (name.empty())
      {
        std::ostringstream oss;
        oss << block_id;
        name = oss.str();
      }
    }
    block_names.push_back(name);
  }

  return block_names;
}

bool
SubProblem::hasBlockMaterialProperty(SubdomainID bid, const std::string & prop_name)
{
  auto it = _map_block_material_props.find(bid);
  if (it == _map_block_material_props.end())
    return false;

  if (it->second.count(prop_name) > 0)
    return true;
  else
    return false;
}

// TODO: remove code duplication by templating
std::set<BoundaryID>
SubProblem::getMaterialPropertyBoundaryIDs(const std::string & prop_name)
{
  std::set<BoundaryID> boundaries;

  for (const auto & it : _map_boundary_material_props)
  {
    const std::set<std::string> & prop_names = it.second;
    std::set<std::string>::iterator name_it = prop_names.find(prop_name);
    if (name_it != prop_names.end())
      boundaries.insert(it.first);
  }

  return boundaries;
}

std::vector<BoundaryName>
SubProblem::getMaterialPropertyBoundaryNames(const std::string & prop_name)
{
  std::set<BoundaryID> boundaries = getMaterialPropertyBoundaryIDs(prop_name);
  std::vector<BoundaryName> boundary_names;
  boundary_names.reserve(boundaries.size());
  const BoundaryInfo & boundary_info = mesh().getMesh().get_boundary_info();

  for (const auto & bnd_id : boundaries)
  {
    BoundaryName name;
    if (bnd_id == Moose::ANY_BOUNDARY_ID)
      name = "ANY_BOUNDARY_ID";
    else
    {
      name = boundary_info.get_sideset_name(bnd_id);
      if (name.empty())
      {
        std::ostringstream oss;
        oss << bnd_id;
        name = oss.str();
      }
    }
    boundary_names.push_back(name);
  }

  return boundary_names;
}

bool
SubProblem::hasBoundaryMaterialProperty(BoundaryID bid, const std::string & prop_name)
{
  auto it = _map_boundary_material_props.find(bid);
  if (it == _map_boundary_material_props.end())
    return false;

  if (it->second.count(prop_name) > 0)
    return true;
  else
    return false;
}

void
SubProblem::storeMatPropName(SubdomainID block_id, const std::string & name)
{
  _map_block_material_props[block_id].insert(name);
}

void
SubProblem::storeMatPropName(BoundaryID boundary_id, const std::string & name)
{
  _map_boundary_material_props[boundary_id].insert(name);
}

void
SubProblem::storeZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name)
{
  _zero_block_material_props[block_id].insert(name);
}

void
SubProblem::storeZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name)
{
  _zero_boundary_material_props[boundary_id].insert(name);
}

void
SubProblem::storeDelayedCheckMatProp(const std::string & requestor,
                                     SubdomainID block_id,
                                     const std::string & name)
{
  _map_block_material_props_check[block_id].insert(std::make_pair(requestor, name));
}

void
SubProblem::storeDelayedCheckMatProp(const std::string & requestor,
                                     BoundaryID boundary_id,
                                     const std::string & name)
{
  _map_boundary_material_props_check[boundary_id].insert(std::make_pair(requestor, name));
}

void
SubProblem::checkBlockMatProps()
{
  checkMatProps(
      _map_block_material_props, _map_block_material_props_check, _zero_block_material_props);
}

void
SubProblem::checkBoundaryMatProps()
{
  checkMatProps(_map_boundary_material_props,
                _map_boundary_material_props_check,
                _zero_boundary_material_props);
}

void
SubProblem::markMatPropRequested(const std::string & prop_name)
{
  _material_property_requested.insert(prop_name);
}

bool
SubProblem::isMatPropRequested(const std::string & prop_name) const
{
  return _material_property_requested.find(prop_name) != _material_property_requested.end();
}

DiracKernelInfo &
SubProblem::diracKernelInfo()
{
  return _dirac_kernel_info;
}

Real
SubProblem::finalNonlinearResidual() const
{
  return 0;
}

unsigned int
SubProblem::nNonlinearIterations() const
{
  return 0;
}

unsigned int
SubProblem::nLinearIterations() const
{
  return 0;
}

void
SubProblem::meshChanged()
{
  mooseError("This system does not support changing the mesh");
}

template <>
std::string
SubProblem::restrictionTypeName<SubdomainID>()
{
  return "block";
}

template <>
std::string
SubProblem::restrictionTypeName<BoundaryID>()
{
  return "boundary";
}

std::string
SubProblem::restrictionCheckName(SubdomainID check_id)
{
  // TODO: Put a better a interface in MOOSE
  std::map<subdomain_id_type, std::string> & name_map = mesh().getMesh().set_subdomain_name_map();
  std::map<subdomain_id_type, std::string>::const_iterator pos = name_map.find(check_id);
  if (pos != name_map.end())
    return pos->second;
  return "";
}

std::string
SubProblem::restrictionCheckName(BoundaryID check_id)
{
  return mesh().getMesh().get_boundary_info().sideset_name(check_id);
}

template <typename T>
void
SubProblem::checkMatProps(std::map<T, std::set<std::string>> & props,
                          std::map<T, std::multimap<std::string, std::string>> & check_props,
                          std::map<T, std::set<MaterialPropertyName>> & zero_props)
{
  // Variable for storing the value for ANY_BLOCK_ID/ANY_BOUNDARY_ID
  T any_id = getAnyID<T>();

  // Variable for storing all available blocks/boundaries from the mesh
  std::set<T> all_ids(mesh().getBlockOrBoundaryIDs<T>());

  // Loop through the properties to check
  for (const auto & check_it : check_props)
  {
    // The current id for the property being checked (BoundaryID || BlockID)
    T check_id = check_it.first;

    // In the case when the material being checked has an ID is set to ANY, then loop through all
    // the possible ids and verify that the material property is defined.
    std::set<T> check_ids = {check_id};
    if (check_id == any_id)
      check_ids = all_ids;

    // Loop through all the block/boundary ids
    for (const auto & id : check_ids)
    {
      // Loop through all the stored properties
      for (const auto & prop_it : check_it.second)
      {
        // Produce an error if the material property is not defined on the current block/boundary
        // and any block/boundary
        // and not is not a zero material property.
        if (props[id].count(prop_it.second) == 0 && props[any_id].count(prop_it.second) == 0 &&
            zero_props[id].count(prop_it.second) == 0 &&
            zero_props[any_id].count(prop_it.second) == 0)
        {
          std::string check_name = restrictionCheckName(id);
          if (check_name.empty())
            check_name = std::to_string(id);
          mooseError("Material property '",
                     prop_it.second,
                     "', requested by '",
                     prop_it.first,
                     "' is not defined on ",
                     restrictionTypeName<T>(),
                     " ",
                     check_name);
        }
      }
    }
  }
}

unsigned int
SubProblem::getAxisymmetricRadialCoord() const
{
  if (_rz_coord_axis == 0)
    return 1; // if the rotation axis is x (0), then the radial direction is y (1)
  else
    return 0; // otherwise the radial direction is assumed to be x, i.e., the rotation axis is y
}

// Anonymous namespace for local helper methods
namespace
{
template <>
SubdomainID
getAnyID()
{
  return Moose::ANY_BLOCK_ID;
}

template <>
BoundaryID
getAnyID()
{
  return Moose::ANY_BOUNDARY_ID;
}
}
<commit_msg>SubProblem, Tagging: More efficient to use std::map<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "SubProblem.h"
#include "Factory.h"
#include "MooseMesh.h"
#include "Conversion.h"
#include "Function.h"
#include "MooseApp.h"
#include "MooseVariableFEImpl.h"
#include "MooseArray.h"

template <>
InputParameters
validParams<SubProblem>()
{
  InputParameters params = validParams<Problem>();
  return params;
}

namespace
{
/**
 * Templated helper that returns either the any block or any boundary ID depending on the template
 * parameter.
 */
template <typename T>
T getAnyID();
}

// SubProblem /////
SubProblem::SubProblem(const InputParameters & parameters)
  : Problem(parameters),
    _factory(_app.getFactory()),
    _nonlocal_cm(),
    _requires_nonlocal_coupling(false),
    _rz_coord_axis(1), // default to RZ rotation around y-axis
    _currently_computing_jacobian(false),
    _computing_nonlinear_residual(false)
{
  unsigned int n_threads = libMesh::n_threads();
  _active_elemental_moose_variables.resize(n_threads);
  _has_active_elemental_moose_variables.resize(n_threads);
  _active_material_property_ids.resize(n_threads);
}

SubProblem::~SubProblem() {}

TagID
SubProblem::addVectorTag(TagName tag_name)
{
  auto existing_tag = _vector_tag_name_to_tag_id.find(tag_name);
  if (existing_tag == _vector_tag_name_to_tag_id.end())
  {
    auto tag_id = _vector_tag_name_to_tag_id.size();

    _vector_tag_name_to_tag_id[tag_name] = tag_id;

    _vector_tag_id_to_tag_name[tag_id] = tag_name;
  }

  return _vector_tag_name_to_tag_id.at(tag_name);
}

TagID
SubProblem::getVectorTag(TagName tag_name)
{
  return _vector_tag_name_to_tag_id.at(tag_name);
}

TagName
SubProblem::vectorTagName(TagID tag)
{
  return _vector_tag_id_to_tag_name[tag];
}

TagID
SubProblem::addMatrixTag(TagName tag_name)
{
  auto existing_tag = _matrix_tag_name_to_tag_id.find(tag_name);
  if (existing_tag == _matrix_tag_name_to_tag_id.end())
  {
    auto tag_id = _matrix_tag_name_to_tag_id.size();

    _matrix_tag_name_to_tag_id[tag_name] = tag_id;

    _matrix_tag_id_to_tag_name[tag_id] = tag_name;
  }

  return _matrix_tag_name_to_tag_id.at(tag_name);
}

TagID
SubProblem::getMatrixTag(TagName tag_name)
{
  return _matrix_tag_name_to_tag_id.at(tag_name);
}

TagName
SubProblem::matrixTagName(TagID tag)
{
  return _matrix_tag_id_to_tag_name[tag];
}

void
SubProblem::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
                                             THREAD_ID tid)
{
  if (!moose_vars.empty())
  {
    _has_active_elemental_moose_variables[tid] = 1;
    _active_elemental_moose_variables[tid] = moose_vars;
  }
}

const std::set<MooseVariableFEBase *> &
SubProblem::getActiveElementalMooseVariables(THREAD_ID tid) const
{
  return _active_elemental_moose_variables[tid];
}

bool
SubProblem::hasActiveElementalMooseVariables(THREAD_ID tid) const
{
  return _has_active_elemental_moose_variables[tid];
}

void
SubProblem::clearActiveElementalMooseVariables(THREAD_ID tid)
{
  _has_active_elemental_moose_variables[tid] = 0;
  _active_elemental_moose_variables[tid].clear();
}

void
SubProblem::setActiveMaterialProperties(const std::set<unsigned int> & mat_prop_ids, THREAD_ID tid)
{
  if (!mat_prop_ids.empty())
    _active_material_property_ids[tid] = mat_prop_ids;
}

const std::set<unsigned int> &
SubProblem::getActiveMaterialProperties(THREAD_ID tid) const
{
  return _active_material_property_ids[tid];
}

bool
SubProblem::hasActiveMaterialProperties(THREAD_ID tid) const
{
  return !_active_material_property_ids[tid].empty();
}

void
SubProblem::clearActiveMaterialProperties(THREAD_ID tid)
{
  _active_material_property_ids[tid].clear();
}

std::set<SubdomainID>
SubProblem::getMaterialPropertyBlocks(const std::string & prop_name)
{
  std::set<SubdomainID> blocks;

  for (const auto & it : _map_block_material_props)
  {
    const std::set<std::string> & prop_names = it.second;
    std::set<std::string>::iterator name_it = prop_names.find(prop_name);
    if (name_it != prop_names.end())
      blocks.insert(it.first);
  }

  return blocks;
}

std::vector<SubdomainName>
SubProblem::getMaterialPropertyBlockNames(const std::string & prop_name)
{
  std::set<SubdomainID> blocks = getMaterialPropertyBlocks(prop_name);
  std::vector<SubdomainName> block_names;
  block_names.reserve(blocks.size());
  for (const auto & block_id : blocks)
  {
    SubdomainName name;
    if (block_id == Moose::ANY_BLOCK_ID)
      name = "ANY_BLOCK_ID";
    else
    {
      name = mesh().getMesh().subdomain_name(block_id);
      if (name.empty())
      {
        std::ostringstream oss;
        oss << block_id;
        name = oss.str();
      }
    }
    block_names.push_back(name);
  }

  return block_names;
}

bool
SubProblem::hasBlockMaterialProperty(SubdomainID bid, const std::string & prop_name)
{
  auto it = _map_block_material_props.find(bid);
  if (it == _map_block_material_props.end())
    return false;

  if (it->second.count(prop_name) > 0)
    return true;
  else
    return false;
}

// TODO: remove code duplication by templating
std::set<BoundaryID>
SubProblem::getMaterialPropertyBoundaryIDs(const std::string & prop_name)
{
  std::set<BoundaryID> boundaries;

  for (const auto & it : _map_boundary_material_props)
  {
    const std::set<std::string> & prop_names = it.second;
    std::set<std::string>::iterator name_it = prop_names.find(prop_name);
    if (name_it != prop_names.end())
      boundaries.insert(it.first);
  }

  return boundaries;
}

std::vector<BoundaryName>
SubProblem::getMaterialPropertyBoundaryNames(const std::string & prop_name)
{
  std::set<BoundaryID> boundaries = getMaterialPropertyBoundaryIDs(prop_name);
  std::vector<BoundaryName> boundary_names;
  boundary_names.reserve(boundaries.size());
  const BoundaryInfo & boundary_info = mesh().getMesh().get_boundary_info();

  for (const auto & bnd_id : boundaries)
  {
    BoundaryName name;
    if (bnd_id == Moose::ANY_BOUNDARY_ID)
      name = "ANY_BOUNDARY_ID";
    else
    {
      name = boundary_info.get_sideset_name(bnd_id);
      if (name.empty())
      {
        std::ostringstream oss;
        oss << bnd_id;
        name = oss.str();
      }
    }
    boundary_names.push_back(name);
  }

  return boundary_names;
}

bool
SubProblem::hasBoundaryMaterialProperty(BoundaryID bid, const std::string & prop_name)
{
  auto it = _map_boundary_material_props.find(bid);
  if (it == _map_boundary_material_props.end())
    return false;

  if (it->second.count(prop_name) > 0)
    return true;
  else
    return false;
}

void
SubProblem::storeMatPropName(SubdomainID block_id, const std::string & name)
{
  _map_block_material_props[block_id].insert(name);
}

void
SubProblem::storeMatPropName(BoundaryID boundary_id, const std::string & name)
{
  _map_boundary_material_props[boundary_id].insert(name);
}

void
SubProblem::storeZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name)
{
  _zero_block_material_props[block_id].insert(name);
}

void
SubProblem::storeZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name)
{
  _zero_boundary_material_props[boundary_id].insert(name);
}

void
SubProblem::storeDelayedCheckMatProp(const std::string & requestor,
                                     SubdomainID block_id,
                                     const std::string & name)
{
  _map_block_material_props_check[block_id].insert(std::make_pair(requestor, name));
}

void
SubProblem::storeDelayedCheckMatProp(const std::string & requestor,
                                     BoundaryID boundary_id,
                                     const std::string & name)
{
  _map_boundary_material_props_check[boundary_id].insert(std::make_pair(requestor, name));
}

void
SubProblem::checkBlockMatProps()
{
  checkMatProps(
      _map_block_material_props, _map_block_material_props_check, _zero_block_material_props);
}

void
SubProblem::checkBoundaryMatProps()
{
  checkMatProps(_map_boundary_material_props,
                _map_boundary_material_props_check,
                _zero_boundary_material_props);
}

void
SubProblem::markMatPropRequested(const std::string & prop_name)
{
  _material_property_requested.insert(prop_name);
}

bool
SubProblem::isMatPropRequested(const std::string & prop_name) const
{
  return _material_property_requested.find(prop_name) != _material_property_requested.end();
}

DiracKernelInfo &
SubProblem::diracKernelInfo()
{
  return _dirac_kernel_info;
}

Real
SubProblem::finalNonlinearResidual() const
{
  return 0;
}

unsigned int
SubProblem::nNonlinearIterations() const
{
  return 0;
}

unsigned int
SubProblem::nLinearIterations() const
{
  return 0;
}

void
SubProblem::meshChanged()
{
  mooseError("This system does not support changing the mesh");
}

template <>
std::string
SubProblem::restrictionTypeName<SubdomainID>()
{
  return "block";
}

template <>
std::string
SubProblem::restrictionTypeName<BoundaryID>()
{
  return "boundary";
}

std::string
SubProblem::restrictionCheckName(SubdomainID check_id)
{
  // TODO: Put a better a interface in MOOSE
  std::map<subdomain_id_type, std::string> & name_map = mesh().getMesh().set_subdomain_name_map();
  std::map<subdomain_id_type, std::string>::const_iterator pos = name_map.find(check_id);
  if (pos != name_map.end())
    return pos->second;
  return "";
}

std::string
SubProblem::restrictionCheckName(BoundaryID check_id)
{
  return mesh().getMesh().get_boundary_info().sideset_name(check_id);
}

template <typename T>
void
SubProblem::checkMatProps(std::map<T, std::set<std::string>> & props,
                          std::map<T, std::multimap<std::string, std::string>> & check_props,
                          std::map<T, std::set<MaterialPropertyName>> & zero_props)
{
  // Variable for storing the value for ANY_BLOCK_ID/ANY_BOUNDARY_ID
  T any_id = getAnyID<T>();

  // Variable for storing all available blocks/boundaries from the mesh
  std::set<T> all_ids(mesh().getBlockOrBoundaryIDs<T>());

  // Loop through the properties to check
  for (const auto & check_it : check_props)
  {
    // The current id for the property being checked (BoundaryID || BlockID)
    T check_id = check_it.first;

    // In the case when the material being checked has an ID is set to ANY, then loop through all
    // the possible ids and verify that the material property is defined.
    std::set<T> check_ids = {check_id};
    if (check_id == any_id)
      check_ids = all_ids;

    // Loop through all the block/boundary ids
    for (const auto & id : check_ids)
    {
      // Loop through all the stored properties
      for (const auto & prop_it : check_it.second)
      {
        // Produce an error if the material property is not defined on the current block/boundary
        // and any block/boundary
        // and not is not a zero material property.
        if (props[id].count(prop_it.second) == 0 && props[any_id].count(prop_it.second) == 0 &&
            zero_props[id].count(prop_it.second) == 0 &&
            zero_props[any_id].count(prop_it.second) == 0)
        {
          std::string check_name = restrictionCheckName(id);
          if (check_name.empty())
            check_name = std::to_string(id);
          mooseError("Material property '",
                     prop_it.second,
                     "', requested by '",
                     prop_it.first,
                     "' is not defined on ",
                     restrictionTypeName<T>(),
                     " ",
                     check_name);
        }
      }
    }
  }
}

unsigned int
SubProblem::getAxisymmetricRadialCoord() const
{
  if (_rz_coord_axis == 0)
    return 1; // if the rotation axis is x (0), then the radial direction is y (1)
  else
    return 0; // otherwise the radial direction is assumed to be x, i.e., the rotation axis is y
}

// Anonymous namespace for local helper methods
namespace
{
template <>
SubdomainID
getAnyID()
{
  return Moose::ANY_BLOCK_ID;
}

template <>
BoundaryID
getAnyID()
{
  return Moose::ANY_BOUNDARY_ID;
}
}
<|endoftext|>


<commit_before>/*
 * FileLogDestination.cpp
 *
 * Copyright (C) 2019 by RStudio, Inc.
 *
 * 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 <shared_core/FileLogDestination.hpp>

#include <boost/thread.hpp>

#include <vector>

#include <shared_core/Logger.hpp>

namespace rstudio {
namespace core {
namespace log {

// FileLogOptions ======================================================================================================
FileLogOptions::FileLogOptions(FilePath in_directory) :
   m_directory(std::move(in_directory)),
   m_fileMode(s_defaultFileMode),
   m_maxSizeMb(s_defaultMaxSizeMb),
   m_doRotation(s_defaultDoRotation),
   m_includePid(s_defaultIncludePid)
{
}

FileLogOptions::FileLogOptions(
   FilePath in_directory,
   std::string in_fileMode,
   double in_maxSizeMb,
   bool in_doRotation,
   bool in_includePid) :
      m_directory(std::move(in_directory)),
      m_fileMode(std::move(in_fileMode)),
      m_maxSizeMb(in_maxSizeMb),
      m_doRotation(in_doRotation),
      m_includePid(in_includePid)
{
}

const FilePath& FileLogOptions::getDirectory() const
{
   return m_directory;
}

const std::string& FileLogOptions::getFileMode() const
{
   return m_fileMode;
}

double FileLogOptions::getMaxSizeMb() const
{
   return m_maxSizeMb;
}

bool FileLogOptions::doRotation() const
{
   return m_doRotation;
}

bool FileLogOptions::includePid() const
{
   return m_includePid;
}

// FileLogDestination ==================================================================================================
struct FileLogDestination::Impl
{
   Impl(unsigned int in_id, const std::string& in_name, FileLogOptions in_options) :
      LogOptions(std::move(in_options)),
      LogName(in_name + ".log"),
      RotatedLogName(in_name + ".old.log"),
      Id(in_id)
   {
      LogOptions.getDirectory().ensureDirectory();
   };

   ~Impl()
   {
      closeLogFile();
   }

   void closeLogFile()
   {
      if (LogOutputStream)
      {
         LogOutputStream->flush();
         LogOutputStream.reset();
      }
   }

   // Returns true if the log file was opened, false otherwise.
   bool openLogFile()
   {
      // We can't safely log in this function.
      Error error = LogOptions.getDirectory().completeChildPath(LogName, LogFile);
      if (error)
         return false;

      error = LogFile.ensureFile();
      if (error)
         return false;

      error = LogFile.openForWrite(LogOutputStream, false);
      if (error)
         return false;

      return true;
   }

   // Returns true if it is safe to log; false otherwise.
   bool rotateLogFile()
   {
      // Calculate the maximum size in bytes.
      const uintmax_t maxSize = 1048576.0 * LogOptions.getMaxSizeMb();

      // Only rotate if we're configured to rotate.
      if (LogOptions.doRotation())
      {
         // Convert MB to B for comparison.
         if (LogFile.getSize() >= maxSize)
         {
            FilePath rotatedLogFile = FilePath(LogOptions.getDirectory()).completeChildPath(RotatedLogName);

            // We can't safely log errors in this function because we'll end up in an infinitely recursive
            // rotateLogFile() call.
            Error error = rotatedLogFile.remove();
            if (error)
               return false;

            // Close the existing log file and then move it.
            closeLogFile();
            error = LogFile.move(rotatedLogFile);
            if (error)
               return false;

            // Now re-open the log file.
            openLogFile();
         }
      }

      return LogFile.getSize() < maxSize;
   }

   FileLogOptions LogOptions;
   FilePath LogFile;
   std::string LogName;
   std::string RotatedLogName;
   boost::mutex Mutex;
   unsigned int Id;
   std::shared_ptr<std::ostream> LogOutputStream;
};

FileLogDestination::FileLogDestination(
   unsigned int in_id,
   const std::string& in_programId,
   FileLogOptions in_logOptions) :
      m_impl(new Impl(in_id, in_programId, std::move(in_logOptions)))
{
}

FileLogDestination::~FileLogDestination()
{
   if (m_impl->LogOutputStream.get())
      m_impl->LogOutputStream->flush();
}

unsigned int FileLogDestination::getId() const
{
   return m_impl->Id;
}

void FileLogDestination::writeLog(LogLevel, const std::string& in_message)
{
   // Lock the mutex before attempting to write.
   boost::unique_lock<boost::mutex> lock(m_impl->Mutex);

   // Open the log file if it's not open. If it fails to open, log nothing.
   if (!m_impl->LogOutputStream && !m_impl->openLogFile())
      return;

   // Rotate the log file if necessary.
   m_impl->rotateLogFile();
   (*m_impl->LogOutputStream) << in_message;
}

} // namespace log
} // namespace core
} // namespace rstudio

<commit_msg>fix an issue where logs are not written to file.<commit_after>/*
 * FileLogDestination.cpp
 *
 * Copyright (C) 2019 by RStudio, Inc.
 *
 * 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 <shared_core/FileLogDestination.hpp>

#include <boost/thread.hpp>

#include <vector>

#include <shared_core/Logger.hpp>

namespace rstudio {
namespace core {
namespace log {

// FileLogOptions ======================================================================================================
FileLogOptions::FileLogOptions(FilePath in_directory) :
   m_directory(std::move(in_directory)),
   m_fileMode(s_defaultFileMode),
   m_maxSizeMb(s_defaultMaxSizeMb),
   m_doRotation(s_defaultDoRotation),
   m_includePid(s_defaultIncludePid)
{
}

FileLogOptions::FileLogOptions(
   FilePath in_directory,
   std::string in_fileMode,
   double in_maxSizeMb,
   bool in_doRotation,
   bool in_includePid) :
      m_directory(std::move(in_directory)),
      m_fileMode(std::move(in_fileMode)),
      m_maxSizeMb(in_maxSizeMb),
      m_doRotation(in_doRotation),
      m_includePid(in_includePid)
{
}

const FilePath& FileLogOptions::getDirectory() const
{
   return m_directory;
}

const std::string& FileLogOptions::getFileMode() const
{
   return m_fileMode;
}

double FileLogOptions::getMaxSizeMb() const
{
   return m_maxSizeMb;
}

bool FileLogOptions::doRotation() const
{
   return m_doRotation;
}

bool FileLogOptions::includePid() const
{
   return m_includePid;
}

// FileLogDestination ==================================================================================================
struct FileLogDestination::Impl
{
   Impl(unsigned int in_id, const std::string& in_name, FileLogOptions in_options) :
      LogOptions(std::move(in_options)),
      LogName(in_name + ".log"),
      RotatedLogName(in_name + ".old.log"),
      Id(in_id)
   {
      LogOptions.getDirectory().ensureDirectory();
   };

   ~Impl()
   {
      closeLogFile();
   }

   void closeLogFile()
   {
      if (LogOutputStream)
      {
         LogOutputStream->flush();
         LogOutputStream.reset();
      }
   }

   // Returns true if the log file was opened, false otherwise.
   bool openLogFile()
   {
      // We can't safely log in this function.
      Error error = LogOptions.getDirectory().completeChildPath(LogName, LogFile);
      if (error)
         return false;

      error = LogFile.ensureFile();
      if (error)
         return false;

      error = LogFile.openForWrite(LogOutputStream, false);
      if (error)
         return false;

      return true;
   }

   // Returns true if it is safe to log; false otherwise.
   bool rotateLogFile()
   {
      // Calculate the maximum size in bytes.
      const uintmax_t maxSize = 1048576.0 * LogOptions.getMaxSizeMb();

      // Only rotate if we're configured to rotate.
      if (LogOptions.doRotation())
      {
         // Convert MB to B for comparison.
         if (LogFile.getSize() >= maxSize)
         {
            FilePath rotatedLogFile = FilePath(LogOptions.getDirectory()).completeChildPath(RotatedLogName);

            // We can't safely log errors in this function because we'll end up in an infinitely recursive
            // rotateLogFile() call.
            Error error = rotatedLogFile.remove();
            if (error)
               return false;

            // Close the existing log file and then move it.
            closeLogFile();
            error = LogFile.move(rotatedLogFile);
            if (error)
               return false;

            // Now re-open the log file.
            openLogFile();
         }
      }

      return LogFile.getSize() < maxSize;
   }

   FileLogOptions LogOptions;
   FilePath LogFile;
   std::string LogName;
   std::string RotatedLogName;
   boost::mutex Mutex;
   unsigned int Id;
   std::shared_ptr<std::ostream> LogOutputStream;
};

FileLogDestination::FileLogDestination(
   unsigned int in_id,
   const std::string& in_programId,
   FileLogOptions in_logOptions) :
      m_impl(new Impl(in_id, in_programId, std::move(in_logOptions)))
{
}

FileLogDestination::~FileLogDestination()
{
   if (m_impl->LogOutputStream.get())
      m_impl->LogOutputStream->flush();
}

unsigned int FileLogDestination::getId() const
{
   return m_impl->Id;
}

void FileLogDestination::writeLog(LogLevel, const std::string& in_message)
{
   // Lock the mutex before attempting to write.
   boost::unique_lock<boost::mutex> lock(m_impl->Mutex);

   // Open the log file if it's not open. If it fails to open, log nothing.
   if (!m_impl->LogOutputStream && !m_impl->openLogFile())
      return;

   // Rotate the log file if necessary.
   m_impl->rotateLogFile();
   (*m_impl->LogOutputStream) << in_message;
   m_impl->LogOutputStream->flush();
}

} // namespace log
} // namespace core
} // namespace rstudio

<|endoftext|>