<commit_before>/*
 * Copyright (C) 2020 ScyllaDB
 *
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <seastar/core/sstring.hh>
#include <seastar/core/file.hh>
#include <seastar/core/sharded.hh>
#include <vector>
#include "sstables/version.hh"
#include "sstables/component_type.hh"
#include "sstables/shareable_components.hh"
#include <seastar/core/shared_ptr.hh>

namespace sstables {

struct entry_descriptor {
    sstring sstdir;
    sstring ks;
    sstring cf;
    int64_t generation;
    sstable_version_types version;
    sstable_format_types format;
    component_type component;

    static entry_descriptor make_descriptor(sstring sstdir, sstring fname);

    entry_descriptor(sstring sstdir, sstring ks, sstring cf, int64_t generation,
                     sstable_version_types version, sstable_format_types format,
                     component_type component)
        : sstdir(sstdir), ks(ks), cf(cf), generation(generation), version(version), format(format), component(component) {}
};

// contains data for loading a sstable using components shared by a single shard;
// can be moved across shards
struct foreign_sstable_open_info {
    foreign_ptr<lw_shared_ptr<shareable_components>> components;
    std::vector<shard_id> owners;
    seastar::file_handle data;
    seastar::file_handle index;
    uint64_t generation;
    sstable_version_types version;
    sstable_format_types format;
    uint64_t uncompressed_data_size;
};

// can only be used locally
struct sstable_open_info {
    lw_shared_ptr<shareable_components> components;
    std::vector<shard_id> owners;
    file data;
    file index;
};

}
<commit_msg>sstables:: kill unused sstables::sstable_open_info<commit_after>/*
 * Copyright (C) 2020 ScyllaDB
 *
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <seastar/core/sstring.hh>
#include <seastar/core/file.hh>
#include <seastar/core/sharded.hh>
#include <vector>
#include "sstables/version.hh"
#include "sstables/component_type.hh"
#include "sstables/shareable_components.hh"
#include <seastar/core/shared_ptr.hh>

namespace sstables {

struct entry_descriptor {
    sstring sstdir;
    sstring ks;
    sstring cf;
    int64_t generation;
    sstable_version_types version;
    sstable_format_types format;
    component_type component;

    static entry_descriptor make_descriptor(sstring sstdir, sstring fname);

    entry_descriptor(sstring sstdir, sstring ks, sstring cf, int64_t generation,
                     sstable_version_types version, sstable_format_types format,
                     component_type component)
        : sstdir(sstdir), ks(ks), cf(cf), generation(generation), version(version), format(format), component(component) {}
};

// contains data for loading a sstable using components shared by a single shard;
// can be moved across shards
struct foreign_sstable_open_info {
    foreign_ptr<lw_shared_ptr<shareable_components>> components;
    std::vector<shard_id> owners;
    seastar::file_handle data;
    seastar::file_handle index;
    uint64_t generation;
    sstable_version_types version;
    sstable_format_types format;
    uint64_t uncompressed_data_size;
};

}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <string.h>

#include "osx/saldata.hxx"
#include "osx/salobj.h"
#include "osx/salframe.h"
#include <AppKit/NSOpenGLView.h>

AquaSalObject::AquaSalObject( AquaSalFrame* pFrame, SystemWindowData* pWindowData ) :
    mpFrame( pFrame ),
    mnClipX( -1 ),
    mnClipY( -1 ),
    mnClipWidth( -1 ),
    mnClipHeight( -1 ),
    mbClip( false ),
    mnX( 0 ),
    mnY( 0 ),
    mnWidth( 20 ),
    mnHeight( 20 )
{
    maSysData.nSize = sizeof( maSysData );
    maSysData.mpNSView = NULL;
    maSysData.mbOpenGL = pWindowData->bOpenGL;

    NSRect aInitFrame = { NSZeroPoint, { 20, 20 } };
    mpClipView = [[NSClipView alloc] initWithFrame: aInitFrame ];
    if( mpClipView )
    {
        [mpFrame->getNSView() addSubview: mpClipView];
        [mpClipView setHidden: YES];
    }
    if (pWindowData->bOpenGL)
    {
        NSOpenGLPixelFormat* pixFormat = NULL;

        if (pWindowData->bLegacy)
        {
            NSOpenGLPixelFormatAttribute aAttributes[] =
            {
                NSOpenGLPFADoubleBuffer,
                NSOpenGLPFAAlphaSize, 8,
                NSOpenGLPFAColorSize, 24,
                NSOpenGLPFAMultisample,
                NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)1,
                NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)4,
                0
            };
            pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:aAttributes];
        }
        else
        {
            NSOpenGLPixelFormatAttribute aAttributes[] =
            {
                NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
                NSOpenGLPFADoubleBuffer,
                NSOpenGLPFAAlphaSize, 8,
                NSOpenGLPFAColorSize, 24,
                NSOpenGLPFAMultisample,
                NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)1,
                NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)4,
                0
            };
            pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:aAttributes];
        }

        maSysData.mpNSView = [[NSOpenGLView alloc] initWithFrame: aInitFrame pixelFormat:pixFormat];
    }
    else
    {
        maSysData.mpNSView = [[NSView alloc] initWithFrame: aInitFrame];
    }

    if( maSysData.mpNSView )
    {
        if( mpClipView )
            [mpClipView setDocumentView: maSysData.mpNSView];
    }
}

AquaSalObject::~AquaSalObject()
{
    if( maSysData.mpNSView )
    {
        NSView *pView = maSysData.mpNSView;
        [pView removeFromSuperview];
        [pView release];
    }
    if( mpClipView )
    {
        [mpClipView removeFromSuperview];
        [mpClipView release];
    }
}

// Please note that the talk about QTMovieView below presumably refers
// to stuff in the QuickTime avmedia thingie, and that QuickTime is
// deprecated, not available for 64-bit code, and won't thus be used
// in a "modern" build of LO anyway. So the relevance of the comment
// is unclear.

/*
   sadly there seems to be no way to impose clipping on a child view,
   especially a QTMovieView which seems to ignore the current context
   completely. Also there is no real way to shape a window; on Aqua a
   similar effect to non-rectangular windows is achieved by using a
   non-opaque window and not painting where one wants the background
   to shine through.

   With respect to SalObject this leaves us to having an NSClipView
   containing the child view. Even a QTMovieView respects the boundaries of
   that, which gives us a clip "region" consisting of one rectangle.
   This is gives us an 80% solution only, though.
*/

void AquaSalObject::ResetClipRegion()
{
    mbClip = false;
    setClippedPosSize();
}

sal_uInt16 AquaSalObject::GetClipRegionType()
{
    return SAL_OBJECT_CLIP_INCLUDERECTS;
}

void AquaSalObject::BeginSetClipRegion( sal_uLong )
{
    mbClip = false;
}

void AquaSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
    if( mbClip )
    {
        if( nX < mnClipX )
        {
            mnClipWidth += mnClipX - nX;
            mnClipX = nX;
        }
        if( nX + nWidth > mnClipX + mnClipWidth )
            mnClipWidth = nX + nWidth - mnClipX;
        if( nY < mnClipY )
        {
            mnClipHeight += mnClipY - nY;
            mnClipY = nY;
        }
        if( nY + nHeight > mnClipY + mnClipHeight )
            mnClipHeight = nY + nHeight - mnClipY;
    }
    else
    {
        mnClipX = nX;
        mnClipY = nY;
        mnClipWidth = nWidth;
        mnClipHeight = nHeight;
        mbClip = true;
    }
}

void AquaSalObject::EndSetClipRegion()
{
    setClippedPosSize();
}

void AquaSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
{
    mnX = nX;
    mnY = nY;
    mnWidth = nWidth;
    mnHeight = nHeight;
    setClippedPosSize();
}

void AquaSalObject::setClippedPosSize()
{
    NSRect aViewRect = { NSZeroPoint, NSMakeSize( mnWidth, mnHeight) };
    if( maSysData.mpNSView )
    {
        NSView* pNSView = maSysData.mpNSView;
        [pNSView setFrame: aViewRect];
    }

    NSRect aClipViewRect = NSMakeRect( mnX, mnY, mnWidth, mnHeight);
    NSPoint aClipPt = NSZeroPoint;
    if( mbClip )
    {
        aClipViewRect.origin.x += mnClipX;
        aClipViewRect.origin.y += mnClipY;
        aClipViewRect.size.width = mnClipWidth;
        aClipViewRect.size.height = mnClipHeight;
        aClipPt.x = mnClipX;
        if( mnClipY == 0 )
            aClipPt.y = mnHeight - mnClipHeight;
    }

    mpFrame->VCLToCocoa( aClipViewRect, false );
    [mpClipView setFrame: aClipViewRect];

    [mpClipView scrollToPoint: aClipPt];
}

void AquaSalObject::Show( bool bVisible )
{
    if( mpClipView )
        [mpClipView setHidden: (bVisible ? NO : YES)];
}

const SystemEnvData* AquaSalObject::GetSystemData() const
{
    return &maSysData;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>prevent potential crash if no SystemWindowData is passed<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <string.h>

#include "osx/saldata.hxx"
#include "osx/salobj.h"
#include "osx/salframe.h"
#include <AppKit/NSOpenGLView.h>

AquaSalObject::AquaSalObject( AquaSalFrame* pFrame, SystemWindowData* pWindowData ) :
    mpFrame( pFrame ),
    mnClipX( -1 ),
    mnClipY( -1 ),
    mnClipWidth( -1 ),
    mnClipHeight( -1 ),
    mbClip( false ),
    mnX( 0 ),
    mnY( 0 ),
    mnWidth( 20 ),
    mnHeight( 20 )
{
    maSysData.nSize = sizeof( maSysData );
    maSysData.mpNSView = NULL;
    maSysData.mbOpenGL = pWindowData->bOpenGL;

    NSRect aInitFrame = { NSZeroPoint, { 20, 20 } };
    mpClipView = [[NSClipView alloc] initWithFrame: aInitFrame ];
    if( mpClipView )
    {
        [mpFrame->getNSView() addSubview: mpClipView];
        [mpClipView setHidden: YES];
    }
    if (pWindowData && pWindowData->bOpenGL)
    {
        NSOpenGLPixelFormat* pixFormat = NULL;

        if (pWindowData->bLegacy)
        {
            NSOpenGLPixelFormatAttribute aAttributes[] =
            {
                NSOpenGLPFADoubleBuffer,
                NSOpenGLPFAAlphaSize, 8,
                NSOpenGLPFAColorSize, 24,
                NSOpenGLPFAMultisample,
                NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)1,
                NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)4,
                0
            };
            pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:aAttributes];
        }
        else
        {
            NSOpenGLPixelFormatAttribute aAttributes[] =
            {
                NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
                NSOpenGLPFADoubleBuffer,
                NSOpenGLPFAAlphaSize, 8,
                NSOpenGLPFAColorSize, 24,
                NSOpenGLPFAMultisample,
                NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)1,
                NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)4,
                0
            };
            pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:aAttributes];
        }

        maSysData.mpNSView = [[NSOpenGLView alloc] initWithFrame: aInitFrame pixelFormat:pixFormat];
    }
    else
    {
        maSysData.mpNSView = [[NSView alloc] initWithFrame: aInitFrame];
    }

    if( maSysData.mpNSView )
    {
        if( mpClipView )
            [mpClipView setDocumentView: maSysData.mpNSView];
    }
}

AquaSalObject::~AquaSalObject()
{
    if( maSysData.mpNSView )
    {
        NSView *pView = maSysData.mpNSView;
        [pView removeFromSuperview];
        [pView release];
    }
    if( mpClipView )
    {
        [mpClipView removeFromSuperview];
        [mpClipView release];
    }
}

// Please note that the talk about QTMovieView below presumably refers
// to stuff in the QuickTime avmedia thingie, and that QuickTime is
// deprecated, not available for 64-bit code, and won't thus be used
// in a "modern" build of LO anyway. So the relevance of the comment
// is unclear.

/*
   sadly there seems to be no way to impose clipping on a child view,
   especially a QTMovieView which seems to ignore the current context
   completely. Also there is no real way to shape a window; on Aqua a
   similar effect to non-rectangular windows is achieved by using a
   non-opaque window and not painting where one wants the background
   to shine through.

   With respect to SalObject this leaves us to having an NSClipView
   containing the child view. Even a QTMovieView respects the boundaries of
   that, which gives us a clip "region" consisting of one rectangle.
   This is gives us an 80% solution only, though.
*/

void AquaSalObject::ResetClipRegion()
{
    mbClip = false;
    setClippedPosSize();
}

sal_uInt16 AquaSalObject::GetClipRegionType()
{
    return SAL_OBJECT_CLIP_INCLUDERECTS;
}

void AquaSalObject::BeginSetClipRegion( sal_uLong )
{
    mbClip = false;
}

void AquaSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
    if( mbClip )
    {
        if( nX < mnClipX )
        {
            mnClipWidth += mnClipX - nX;
            mnClipX = nX;
        }
        if( nX + nWidth > mnClipX + mnClipWidth )
            mnClipWidth = nX + nWidth - mnClipX;
        if( nY < mnClipY )
        {
            mnClipHeight += mnClipY - nY;
            mnClipY = nY;
        }
        if( nY + nHeight > mnClipY + mnClipHeight )
            mnClipHeight = nY + nHeight - mnClipY;
    }
    else
    {
        mnClipX = nX;
        mnClipY = nY;
        mnClipWidth = nWidth;
        mnClipHeight = nHeight;
        mbClip = true;
    }
}

void AquaSalObject::EndSetClipRegion()
{
    setClippedPosSize();
}

void AquaSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
{
    mnX = nX;
    mnY = nY;
    mnWidth = nWidth;
    mnHeight = nHeight;
    setClippedPosSize();
}

void AquaSalObject::setClippedPosSize()
{
    NSRect aViewRect = { NSZeroPoint, NSMakeSize( mnWidth, mnHeight) };
    if( maSysData.mpNSView )
    {
        NSView* pNSView = maSysData.mpNSView;
        [pNSView setFrame: aViewRect];
    }

    NSRect aClipViewRect = NSMakeRect( mnX, mnY, mnWidth, mnHeight);
    NSPoint aClipPt = NSZeroPoint;
    if( mbClip )
    {
        aClipViewRect.origin.x += mnClipX;
        aClipViewRect.origin.y += mnClipY;
        aClipViewRect.size.width = mnClipWidth;
        aClipViewRect.size.height = mnClipHeight;
        aClipPt.x = mnClipX;
        if( mnClipY == 0 )
            aClipPt.y = mnHeight - mnClipHeight;
    }

    mpFrame->VCLToCocoa( aClipViewRect, false );
    [mpClipView setFrame: aClipViewRect];

    [mpClipView scrollToPoint: aClipPt];
}

void AquaSalObject::Show( bool bVisible )
{
    if( mpClipView )
        [mpClipView setHidden: (bVisible ? NO : YES)];
}

const SystemEnvData* AquaSalObject::GetSystemData() const
{
    return &maSysData;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "config/full_system.hh"

#if FULL_SYSTEM
#include "arch/x86/interrupts.hh"
#endif
#include "arch/x86/intregs.hh"
#include "arch/x86/miscregs.hh"
#include "arch/x86/segmentregs.hh"
#include "arch/x86/utility.hh"
#include "arch/x86/x86_traits.hh"
#include "cpu/base.hh"
#include "sim/system.hh"

namespace X86ISA {

uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
#if FULL_SYSTEM
    panic("getArgument() not implemented for x86!\n");
#else
    panic("getArgument() only implemented for FULL_SYSTEM\n");
    M5_DUMMY_RETURN
#endif
}

# if FULL_SYSTEM
void initCPU(ThreadContext *tc, int cpuId)
{
    // The otherwise unmodified integer registers should be set to 0.
    for (int index = 0; index < NUM_INTREGS; index++) {
        tc->setIntReg(index, 0);
    }

    // These next two loops zero internal microcode and implicit registers.
    // They aren't specified by the ISA but are used internally by M5's
    // implementation.
    for (int index = 0; index < NumMicroIntRegs; index++) {
        tc->setIntReg(INTREG_MICRO(index), 0);
    }

    for (int index = 0; index < NumImplicitIntRegs; index++) {
        tc->setIntReg(INTREG_IMPLICIT(index), 0);
    }

    // Set integer register EAX to 0 to indicate that the optional BIST
    // passed. No BIST actually runs, but software may still check this
    // register for errors.
    tc->setIntReg(INTREG_RAX, 0);

    //The following values are dictated by the architecture for after a RESET#
    tc->setMiscReg(MISCREG_CR0, 0x0000000060000010ULL);
    tc->setMiscReg(MISCREG_CR2, 0);
    tc->setMiscReg(MISCREG_CR3, 0);
    tc->setMiscReg(MISCREG_CR4, 0);
    tc->setMiscReg(MISCREG_CR8, 0);

    tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL);

    tc->setMiscReg(MISCREG_EFER, 0);

    SegAttr dataAttr = 0;
    dataAttr.writable = 1;
    dataAttr.readable = 1;
    dataAttr.expandDown = 0;
    dataAttr.dpl = 0;
    dataAttr.defaultSize = 0;

    for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) {
        tc->setMiscReg(MISCREG_SEG_SEL(seg), 0);
        tc->setMiscReg(MISCREG_SEG_BASE(seg), 0);
        tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0);
        tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff);
        tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr);
    }

    SegAttr codeAttr = 0;
    codeAttr.writable = 0;
    codeAttr.readable = 1;
    codeAttr.expandDown = 0;
    codeAttr.dpl = 0;
    codeAttr.defaultSize = 0;

    tc->setMiscReg(MISCREG_CS, 0xf000);
    tc->setMiscReg(MISCREG_CS_BASE,
            0x00000000ffff0000ULL);
    tc->setMiscReg(MISCREG_CS_EFF_BASE,
            0x00000000ffff0000ULL);
    // This has the base value pre-added.
    tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff);
    tc->setMiscReg(MISCREG_CS_ATTR, codeAttr);

    tc->setPC(0x000000000000fff0ULL +
            tc->readMiscReg(MISCREG_CS_BASE));
    tc->setNextPC(tc->readPC() + sizeof(MachInst));

    tc->setMiscReg(MISCREG_TSG_BASE, 0);
    tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);

    tc->setMiscReg(MISCREG_IDTR_BASE, 0);
    tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);

    tc->setMiscReg(MISCREG_TSL, 0);
    tc->setMiscReg(MISCREG_TSL_BASE, 0);
    tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff);
    tc->setMiscReg(MISCREG_TSL_ATTR, 0);

    tc->setMiscReg(MISCREG_TR, 0);
    tc->setMiscReg(MISCREG_TR_BASE, 0);
    tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff);
    tc->setMiscReg(MISCREG_TR_ATTR, 0);

    // This value should be the family/model/stepping of the processor.
    // (page 418). It should be consistent with the value from CPUID, but the
    // actual value probably doesn't matter much.
    tc->setIntReg(INTREG_RDX, 0);

    // TODO initialize x87, 64 bit, and 128 bit media state

    tc->setMiscReg(MISCREG_MTRRCAP, 0x0508);
    for (int i = 0; i < 8; i++) {
        tc->setMiscReg(MISCREG_MTRR_PHYS_BASE(i), 0);
        tc->setMiscReg(MISCREG_MTRR_PHYS_MASK(i), 0);
    }
    tc->setMiscReg(MISCREG_MTRR_FIX_64K_00000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_16K_80000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_16K_A0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_C0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_C8000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_D0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_D8000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_E0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_E8000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_F0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_F8000, 0);

    tc->setMiscReg(MISCREG_DEF_TYPE, 0);

    tc->setMiscReg(MISCREG_MCG_CAP, 0x104);
    tc->setMiscReg(MISCREG_MCG_STATUS, 0);
    tc->setMiscReg(MISCREG_MCG_CTL, 0);

    for (int i = 0; i < 5; i++) {
        tc->setMiscReg(MISCREG_MC_CTL(i), 0);
        tc->setMiscReg(MISCREG_MC_STATUS(i), 0);
        tc->setMiscReg(MISCREG_MC_ADDR(i), 0);
        tc->setMiscReg(MISCREG_MC_MISC(i), 0);
    }

    tc->setMiscReg(MISCREG_DR0, 0);
    tc->setMiscReg(MISCREG_DR1, 0);
    tc->setMiscReg(MISCREG_DR2, 0);
    tc->setMiscReg(MISCREG_DR3, 0);

    tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL);
    tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL);

    tc->setMiscReg(MISCREG_TSC, 0);
    tc->setMiscReg(MISCREG_TSC_AUX, 0);

    for (int i = 0; i < 4; i++) {
        tc->setMiscReg(MISCREG_PERF_EVT_SEL(i), 0);
        tc->setMiscReg(MISCREG_PERF_EVT_CTR(i), 0);
    }

    tc->setMiscReg(MISCREG_STAR, 0);
    tc->setMiscReg(MISCREG_LSTAR, 0);
    tc->setMiscReg(MISCREG_CSTAR, 0);

    tc->setMiscReg(MISCREG_SF_MASK, 0);

    tc->setMiscReg(MISCREG_KERNEL_GS_BASE, 0);

    tc->setMiscReg(MISCREG_SYSENTER_CS, 0);
    tc->setMiscReg(MISCREG_SYSENTER_ESP, 0);
    tc->setMiscReg(MISCREG_SYSENTER_EIP, 0);

    tc->setMiscReg(MISCREG_PAT, 0x0007040600070406ULL);

    tc->setMiscReg(MISCREG_SYSCFG, 0x20601);

    tc->setMiscReg(MISCREG_IORR_BASE0, 0);
    tc->setMiscReg(MISCREG_IORR_BASE1, 0);

    tc->setMiscReg(MISCREG_IORR_MASK0, 0);
    tc->setMiscReg(MISCREG_IORR_MASK1, 0);

    tc->setMiscReg(MISCREG_TOP_MEM, 0x4000000);
    tc->setMiscReg(MISCREG_TOP_MEM2, 0x0);

    tc->setMiscReg(MISCREG_DEBUG_CTL_MSR, 0);
    tc->setMiscReg(MISCREG_LAST_BRANCH_FROM_IP, 0);
    tc->setMiscReg(MISCREG_LAST_BRANCH_TO_IP, 0);
    tc->setMiscReg(MISCREG_LAST_EXCEPTION_FROM_IP, 0);
    tc->setMiscReg(MISCREG_LAST_EXCEPTION_TO_IP, 0);

    // Invalidate the caches (this should already be done for us)

    // TODO Turn on the APIC. This should be handled elsewhere but it isn't
    // currently being handled at all.

    LocalApicBase lApicBase = 0;
    lApicBase.base = 0xFEE00000 >> 12;
    lApicBase.enable = 1;
    lApicBase.bsp = (cpuId == 0);
    tc->setMiscReg(MISCREG_APIC_BASE, lApicBase);

    Interrupts * interrupts = dynamic_cast<Interrupts *>(
            tc->getCpuPtr()->getInterruptController());
    assert(interrupts);

    interrupts->setRegNoEffect(APIC_ID, cpuId << 24);

    interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14);

    interrupts->setClock(tc->getCpuPtr()->ticks(16));

    // TODO Set the SMRAM base address (SMBASE) to 0x00030000

    tc->setMiscReg(MISCREG_VM_CR, 0);
    tc->setMiscReg(MISCREG_IGNNE, 0);
    tc->setMiscReg(MISCREG_SMM_CTL, 0);
    tc->setMiscReg(MISCREG_VM_HSAVE_PA, 0);
}

#endif

#if FULL_SYSTEM
void startupCPU(ThreadContext *tc, int cpuId)
{
    if (cpuId == 0) {
        tc->activate(0);
    } else {
        // This is an application processor (AP). It should be initialized to
        // look like only the BIOS POST has run on it and put then put it into
        // a halted state.
        tc->suspend();
    }
}

#else

void startupCPU(ThreadContext *tc, int cpuId)
{
    tc->activate(0);
}

#endif

} //namespace X86_ISA
<commit_msg>X86: Condense the startupCPU code.<commit_after>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "config/full_system.hh"

#if FULL_SYSTEM
#include "arch/x86/interrupts.hh"
#endif
#include "arch/x86/intregs.hh"
#include "arch/x86/miscregs.hh"
#include "arch/x86/segmentregs.hh"
#include "arch/x86/utility.hh"
#include "arch/x86/x86_traits.hh"
#include "cpu/base.hh"
#include "sim/system.hh"

namespace X86ISA {

uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
#if FULL_SYSTEM
    panic("getArgument() not implemented for x86!\n");
#else
    panic("getArgument() only implemented for FULL_SYSTEM\n");
    M5_DUMMY_RETURN
#endif
}

# if FULL_SYSTEM
void initCPU(ThreadContext *tc, int cpuId)
{
    // The otherwise unmodified integer registers should be set to 0.
    for (int index = 0; index < NUM_INTREGS; index++) {
        tc->setIntReg(index, 0);
    }

    // These next two loops zero internal microcode and implicit registers.
    // They aren't specified by the ISA but are used internally by M5's
    // implementation.
    for (int index = 0; index < NumMicroIntRegs; index++) {
        tc->setIntReg(INTREG_MICRO(index), 0);
    }

    for (int index = 0; index < NumImplicitIntRegs; index++) {
        tc->setIntReg(INTREG_IMPLICIT(index), 0);
    }

    // Set integer register EAX to 0 to indicate that the optional BIST
    // passed. No BIST actually runs, but software may still check this
    // register for errors.
    tc->setIntReg(INTREG_RAX, 0);

    //The following values are dictated by the architecture for after a RESET#
    tc->setMiscReg(MISCREG_CR0, 0x0000000060000010ULL);
    tc->setMiscReg(MISCREG_CR2, 0);
    tc->setMiscReg(MISCREG_CR3, 0);
    tc->setMiscReg(MISCREG_CR4, 0);
    tc->setMiscReg(MISCREG_CR8, 0);

    tc->setMiscReg(MISCREG_RFLAGS, 0x0000000000000002ULL);

    tc->setMiscReg(MISCREG_EFER, 0);

    SegAttr dataAttr = 0;
    dataAttr.writable = 1;
    dataAttr.readable = 1;
    dataAttr.expandDown = 0;
    dataAttr.dpl = 0;
    dataAttr.defaultSize = 0;

    for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) {
        tc->setMiscReg(MISCREG_SEG_SEL(seg), 0);
        tc->setMiscReg(MISCREG_SEG_BASE(seg), 0);
        tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0);
        tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff);
        tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr);
    }

    SegAttr codeAttr = 0;
    codeAttr.writable = 0;
    codeAttr.readable = 1;
    codeAttr.expandDown = 0;
    codeAttr.dpl = 0;
    codeAttr.defaultSize = 0;

    tc->setMiscReg(MISCREG_CS, 0xf000);
    tc->setMiscReg(MISCREG_CS_BASE,
            0x00000000ffff0000ULL);
    tc->setMiscReg(MISCREG_CS_EFF_BASE,
            0x00000000ffff0000ULL);
    // This has the base value pre-added.
    tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff);
    tc->setMiscReg(MISCREG_CS_ATTR, codeAttr);

    tc->setPC(0x000000000000fff0ULL +
            tc->readMiscReg(MISCREG_CS_BASE));
    tc->setNextPC(tc->readPC() + sizeof(MachInst));

    tc->setMiscReg(MISCREG_TSG_BASE, 0);
    tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);

    tc->setMiscReg(MISCREG_IDTR_BASE, 0);
    tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);

    tc->setMiscReg(MISCREG_TSL, 0);
    tc->setMiscReg(MISCREG_TSL_BASE, 0);
    tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff);
    tc->setMiscReg(MISCREG_TSL_ATTR, 0);

    tc->setMiscReg(MISCREG_TR, 0);
    tc->setMiscReg(MISCREG_TR_BASE, 0);
    tc->setMiscReg(MISCREG_TR_LIMIT, 0xffff);
    tc->setMiscReg(MISCREG_TR_ATTR, 0);

    // This value should be the family/model/stepping of the processor.
    // (page 418). It should be consistent with the value from CPUID, but the
    // actual value probably doesn't matter much.
    tc->setIntReg(INTREG_RDX, 0);

    // TODO initialize x87, 64 bit, and 128 bit media state

    tc->setMiscReg(MISCREG_MTRRCAP, 0x0508);
    for (int i = 0; i < 8; i++) {
        tc->setMiscReg(MISCREG_MTRR_PHYS_BASE(i), 0);
        tc->setMiscReg(MISCREG_MTRR_PHYS_MASK(i), 0);
    }
    tc->setMiscReg(MISCREG_MTRR_FIX_64K_00000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_16K_80000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_16K_A0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_C0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_C8000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_D0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_D8000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_E0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_E8000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_F0000, 0);
    tc->setMiscReg(MISCREG_MTRR_FIX_4K_F8000, 0);

    tc->setMiscReg(MISCREG_DEF_TYPE, 0);

    tc->setMiscReg(MISCREG_MCG_CAP, 0x104);
    tc->setMiscReg(MISCREG_MCG_STATUS, 0);
    tc->setMiscReg(MISCREG_MCG_CTL, 0);

    for (int i = 0; i < 5; i++) {
        tc->setMiscReg(MISCREG_MC_CTL(i), 0);
        tc->setMiscReg(MISCREG_MC_STATUS(i), 0);
        tc->setMiscReg(MISCREG_MC_ADDR(i), 0);
        tc->setMiscReg(MISCREG_MC_MISC(i), 0);
    }

    tc->setMiscReg(MISCREG_DR0, 0);
    tc->setMiscReg(MISCREG_DR1, 0);
    tc->setMiscReg(MISCREG_DR2, 0);
    tc->setMiscReg(MISCREG_DR3, 0);

    tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL);
    tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL);

    tc->setMiscReg(MISCREG_TSC, 0);
    tc->setMiscReg(MISCREG_TSC_AUX, 0);

    for (int i = 0; i < 4; i++) {
        tc->setMiscReg(MISCREG_PERF_EVT_SEL(i), 0);
        tc->setMiscReg(MISCREG_PERF_EVT_CTR(i), 0);
    }

    tc->setMiscReg(MISCREG_STAR, 0);
    tc->setMiscReg(MISCREG_LSTAR, 0);
    tc->setMiscReg(MISCREG_CSTAR, 0);

    tc->setMiscReg(MISCREG_SF_MASK, 0);

    tc->setMiscReg(MISCREG_KERNEL_GS_BASE, 0);

    tc->setMiscReg(MISCREG_SYSENTER_CS, 0);
    tc->setMiscReg(MISCREG_SYSENTER_ESP, 0);
    tc->setMiscReg(MISCREG_SYSENTER_EIP, 0);

    tc->setMiscReg(MISCREG_PAT, 0x0007040600070406ULL);

    tc->setMiscReg(MISCREG_SYSCFG, 0x20601);

    tc->setMiscReg(MISCREG_IORR_BASE0, 0);
    tc->setMiscReg(MISCREG_IORR_BASE1, 0);

    tc->setMiscReg(MISCREG_IORR_MASK0, 0);
    tc->setMiscReg(MISCREG_IORR_MASK1, 0);

    tc->setMiscReg(MISCREG_TOP_MEM, 0x4000000);
    tc->setMiscReg(MISCREG_TOP_MEM2, 0x0);

    tc->setMiscReg(MISCREG_DEBUG_CTL_MSR, 0);
    tc->setMiscReg(MISCREG_LAST_BRANCH_FROM_IP, 0);
    tc->setMiscReg(MISCREG_LAST_BRANCH_TO_IP, 0);
    tc->setMiscReg(MISCREG_LAST_EXCEPTION_FROM_IP, 0);
    tc->setMiscReg(MISCREG_LAST_EXCEPTION_TO_IP, 0);

    // Invalidate the caches (this should already be done for us)

    // TODO Turn on the APIC. This should be handled elsewhere but it isn't
    // currently being handled at all.

    LocalApicBase lApicBase = 0;
    lApicBase.base = 0xFEE00000 >> 12;
    lApicBase.enable = 1;
    lApicBase.bsp = (cpuId == 0);
    tc->setMiscReg(MISCREG_APIC_BASE, lApicBase);

    Interrupts * interrupts = dynamic_cast<Interrupts *>(
            tc->getCpuPtr()->getInterruptController());
    assert(interrupts);

    interrupts->setRegNoEffect(APIC_ID, cpuId << 24);

    interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14);

    interrupts->setClock(tc->getCpuPtr()->ticks(16));

    // TODO Set the SMRAM base address (SMBASE) to 0x00030000

    tc->setMiscReg(MISCREG_VM_CR, 0);
    tc->setMiscReg(MISCREG_IGNNE, 0);
    tc->setMiscReg(MISCREG_SMM_CTL, 0);
    tc->setMiscReg(MISCREG_VM_HSAVE_PA, 0);
}

#endif

void startupCPU(ThreadContext *tc, int cpuId)
{
#if FULL_SYSTEM
    if (cpuId == 0) {
        tc->activate(0);
    } else {
        // This is an application processor (AP). It should be initialized to
        // look like only the BIOS POST has run on it and put then put it into
        // a halted state.
        tc->suspend(0);
    }
#else
    tc->activate(0);
#endif
}

} //namespace X86_ISA
<|endoftext|>


<commit_before>#include "Heartbeat.h"
#include "Arduino.h"
#include "TimerOne.h"

/**
 * @brief ISR for toggling the heartbeat LED.
 */
void Heartbeat::toggle(void){
	#if defined(__MK20DX256__) || defined(__MK20DX128__)
		// The teensy does have a toggle register!
		GPIOC_PTOR = 1 << 5;
	#else
		// This doesn't have a toggle register, so
		// we have to do this manually.
		PORTB = 1 << 5 ^ PORTB;
	#endif

  // turn off the led
  PORTB = 0 << 5 & PORTB;
}

/**
 * @brief Starts the heartbeat LED on PB5 using a timer.
 */
void Heartbeat::start(void){
	// Make sure pin is output.
	#if defined(__MK20DX256__) || defined(__MK20DX128__)
		pinMode(13, OUTPUT);
	#else
		DDRB = 1 << 5 | DDRB;
	#endif

	// Start a timer.
	Timer1.initialize();

	// Make sure we are not using any other ISR's.
	Timer1.detachInterrupt();

	// Attach a static toggle pin ISR to said timer every 1,000,000 microseconds.
	Timer1.attachInterrupt(Heartbeat::toggle, 1000000);
}

/**
 * @brief Stops the heartbeat LED on PB5 using a timer.
 */
void Heartbeat::stop(void){
	// Disable interrupts for our timer.
	Timer1.detachInterrupt();
}

/**
 * @brief Blinks the LED much quicker to show that we are in an error state.
 */
void Heartbeat::panic(void){
	// Make sure we got rid of the old heartbeat ISR.
	Timer1.detachInterrupt();

	// Attach a static toggle pin ISR to said timer every 50,000 microseconds.
	Timer1.attachInterrupt(Heartbeat::toggle, 50000);
}<commit_msg>added the led off code in the proper spot<commit_after>#include "Heartbeat.h"
#include "Arduino.h"
#include "TimerOne.h"

/**
 * @brief ISR for toggling the heartbeat LED.
 */
void Heartbeat::toggle(void){
	#if defined(__MK20DX256__) || defined(__MK20DX128__)
		// The teensy does have a toggle register!
		GPIOC_PTOR = 1 << 5;
	#else
		// This doesn't have a toggle register, so
		// we have to do this manually.
		PORTB = 1 << 5 ^ PORTB;
	#endif
}

/**
 * @brief Starts the heartbeat LED on PB5 using a timer.
 */
void Heartbeat::start(void){
	// Make sure pin is output.
	#if defined(__MK20DX256__) || defined(__MK20DX128__)
		pinMode(13, OUTPUT);
	#else
		DDRB = 1 << 5 | DDRB;
	#endif

	// Start a timer.
	Timer1.initialize();

	// Make sure we are not using any other ISR's.
	Timer1.detachInterrupt();

	// Attach a static toggle pin ISR to said timer every 1,000,000 microseconds.
	Timer1.attachInterrupt(Heartbeat::toggle, 1000000);
}

/**
 * @brief Stops the heartbeat LED on PB5 using a timer.
 */
void Heartbeat::stop(void){
	// turn off the led
  	PORTB = 0 << 5 & PORTB;
	// Disable interrupts for our timer.
	Timer1.detachInterrupt();
}

/**
 * @brief Blinks the LED much quicker to show that we are in an error state.
 */
void Heartbeat::panic(void){
	// Make sure we got rid of the old heartbeat ISR.
	Timer1.detachInterrupt();

	// Attach a static toggle pin ISR to said timer every 50,000 microseconds.
	Timer1.attachInterrupt(Heartbeat::toggle, 50000);
}
<|endoftext|>


<commit_before>// This is core/vnl/algo/vnl_lbfgsb.cxx
#ifdef VCL_NEEDS_PRAGMA_INTERFACE
#pragma implementation
#endif
//:
// \file
//
// \author Brad King, Kitware Inc.
// \date   28 Aug 07
//
//-----------------------------------------------------------------------------

#include "vnl_lbfgsb.h"
#include <vcl_cstring.h>

#include <vnl/algo/vnl_netlib.h> // setulb_()

//----------------------------------------------------------------------------
vnl_lbfgsb::vnl_lbfgsb(): f_(0)
{
  init_parameters();
}

//----------------------------------------------------------------------------
vnl_lbfgsb::vnl_lbfgsb(vnl_cost_function& f): f_(&f)
{
  init_parameters();
}

//----------------------------------------------------------------------------
void vnl_lbfgsb::init_parameters()
{
  long n = this->f_->get_number_of_unknowns();
  this->bound_selection_.set_size(n);
  this->bound_selection_.fill(0);
  this->max_corrections_ = 5;
  this->convergence_factor_ = 1e+7;
  this->projected_gradient_tolerance_ = 1e-5;
}

//----------------------------------------------------------------------------
bool vnl_lbfgsb::minimize(vnl_vector<double>& x)
{
  // Basic setup.
  long n = this->f_->get_number_of_unknowns();
  long m = this->max_corrections_;

  // Function and gradient.
  double f = 0;
  vnl_vector<double> gradient(n);

  // Working space.
  vnl_vector<double> wa((2*m+4)*n + 12*m*m + 12*m);
  vnl_vector<long> iwa(3*n);
  char csave[60];
  long lsave[4];
  long isave[44];
  double dsave[29];

  // Task communication.
  char task[61] =
    "START                                                       ";

  // Verbosity level inside lbfgs implementation.
  long const iprint = -1;

  // Initialize iteration.
  this->num_evaluations_ = 0;
  this->num_iterations_ = 0;

  // TODO: Deal with verbose_, check_derivatives_, trace, xtol,
  // maxfev, ftol, gtol, epsfcn members of vnl_nonlinear_minimizer.

  bool ok = true;
  for(;;)
    {
    // Call the L-BFGS-B code.
    v3p_netlib_setulb_(
      &n,
      &m,
      x.data_block(),
      this->lower_bound_.data_block(),
      this->upper_bound_.data_block(),
      this->bound_selection_.data_block(),
      &f, gradient.data_block(),
      &this->convergence_factor_,
      &this->projected_gradient_tolerance_,
      wa.data_block(),
      iwa.data_block(),
      task,
      &iprint,
      csave, lsave, isave, dsave
      );

    // Check the current task.
    if(vcl_strncmp("FG", task, 2) == 0)
      {
      // Evaluate the function and gradient.
      this->f_->compute(x, &f, &gradient);

      if(this->num_evaluations_ == 0)
        {
        this->start_error_ = f;
        }
      this->report_eval(f);
      }
    else if(vcl_strncmp("NEW_X", task, 5) == 0)
      {
      // dsave[12] = the infinity norm of the projected gradient
      this->inf_norm_projected_gradient_ = dsave[12];

      // Iteration.a
      if(this->report_iter())
        {
        this->failure_code_ = FAILED_USER_REQUEST;
        ok = false;
        break;
        }
      }
    else if(vcl_strncmp("ERROR", task, 5) == 0)
      {
      // some error
      this->failure_code_ = ERROR_FAILURE;
      ok = false;
      break;
      }
    else if(vcl_strncmp("CONVERGENCE", task, 11) == 0)
      {
      // convergence has been reached
      this->end_error_ = f;

      if(vcl_strncmp("CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH",
                     task, 47) == 0)
        {
        // function tolerance reached
        this->failure_code_ = CONVERGED_FTOL;
        }
      if(vcl_strncmp("CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL",
                     task, 48) == 0)
        {
        // gradient tolerance reached
        this->failure_code_ = CONVERGED_GTOL;
        }
      break;
      }
    else
      {
      // unknown task
      this->failure_code_ = ERROR_FAILURE;
      ok = false;
      break;
      }

    if(this->num_evaluations_ > this->get_max_function_evals())
      {
      this->failure_code_ = FAILED_TOO_MANY_ITERATIONS;
      ok = false;
      break;
      }
    }

  return ok;
}
<commit_msg>ENH: Added support to vnl_lbfgsb for trace.  Patch from Tom Vercauteren on ITK users list.<commit_after>// This is core/vnl/algo/vnl_lbfgsb.cxx
#ifdef VCL_NEEDS_PRAGMA_INTERFACE
#pragma implementation
#endif
//:
// \file
//
// \author Brad King, Kitware Inc.
// \date   28 Aug 07
//
//-----------------------------------------------------------------------------

#include "vnl_lbfgsb.h"
#include <vcl_cstring.h>
#include <vcl_iostream.h>

#include <vnl/algo/vnl_netlib.h> // setulb_()

//----------------------------------------------------------------------------
vnl_lbfgsb::vnl_lbfgsb(): f_(0)
{
  init_parameters();
}

//----------------------------------------------------------------------------
vnl_lbfgsb::vnl_lbfgsb(vnl_cost_function& f): f_(&f)
{
  init_parameters();
}

//----------------------------------------------------------------------------
void vnl_lbfgsb::init_parameters()
{
  long n = this->f_->get_number_of_unknowns();
  this->bound_selection_.set_size(n);
  this->bound_selection_.fill(0);
  this->max_corrections_ = 5;
  this->convergence_factor_ = 1e+7;
  this->projected_gradient_tolerance_ = 1e-5;
}

//----------------------------------------------------------------------------
bool vnl_lbfgsb::minimize(vnl_vector<double>& x)
{
  // Basic setup.
  long n = this->f_->get_number_of_unknowns();
  long m = this->max_corrections_;

  // Function and gradient.
  double f = 0;
  vnl_vector<double> gradient(n);

  // Working space.
  vnl_vector<double> wa((2*m+4)*n + 12*m*m + 12*m);
  vnl_vector<long> iwa(3*n);
  char csave[60];
  long lsave[4];
  long isave[44];
  double dsave[29];

  // Task communication.
  char task[61] =
    "START                                                       ";

  // Verbosity level inside lbfgs implementation.
  // (-1 no o/p, 0 start and end, 1 every iter)
  long const iprint = trace ? 1 : -1;

  // Initialize iteration.
  this->num_evaluations_ = 0;
  this->num_iterations_ = 0;

  // TODO: Deal with verbose_, check_derivatives_, trace, xtol,
  // maxfev, ftol, gtol, epsfcn members of vnl_nonlinear_minimizer.

  bool ok = true;
  for(;;)
    {
    // Call the L-BFGS-B code.
    v3p_netlib_setulb_(
      &n,
      &m,
      x.data_block(),
      this->lower_bound_.data_block(),
      this->upper_bound_.data_block(),
      this->bound_selection_.data_block(),
      &f, gradient.data_block(),
      &this->convergence_factor_,
      &this->projected_gradient_tolerance_,
      wa.data_block(),
      iwa.data_block(),
      task,
      &iprint,
      csave, lsave, isave, dsave
      );

    // Check the current task.
    if(vcl_strncmp("FG", task, 2) == 0)
      {
      // Evaluate the function and gradient.
      this->f_->compute(x, &f, &gradient);

      if(this->num_evaluations_ == 0)
        {
        this->start_error_ = f;
        }
      this->report_eval(f);
      }
    else if(vcl_strncmp("NEW_X", task, 5) == 0)
      {
      // dsave[12] = the infinity norm of the projected gradient
      this->inf_norm_projected_gradient_ = dsave[12];

      // Iteration.a
      if(this->report_iter())
        {
        this->failure_code_ = FAILED_USER_REQUEST;
        ok = false;
        break;
        }
      }
    else if(vcl_strncmp("ERROR", task, 5) == 0)
      {
      // some error
      this->failure_code_ = ERROR_FAILURE;
      ok = false;
      break;
      }
    else if(vcl_strncmp("CONVERGENCE", task, 11) == 0)
      {
      // convergence has been reached
      this->end_error_ = f;

      if(vcl_strncmp("CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH",
                     task, 47) == 0)
        {
        // function tolerance reached
        this->failure_code_ = CONVERGED_FTOL;
        }
      else if(vcl_strncmp("CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL",
                          task, 48) == 0)
        {
        // gradient tolerance reached
        this->failure_code_ = CONVERGED_GTOL;
        }
      else
        {
        this->failure_code_ = ERROR_FAILURE;
        if(trace)
          {
          vcl_cerr << "Unknown convergence type: " << task << std::endl;
          }
        }
      break;
      }
    else
      {
      // unknown task
      this->failure_code_ = ERROR_FAILURE;
      if(trace)
        {
        vcl_cerr << "Unknown failure with task: " << task << std::endl;
        }
      ok = false;
      break;
      }

    if(this->num_evaluations_ > this->get_max_function_evals())
      {
      this->failure_code_ = FAILED_TOO_MANY_ITERATIONS;
      ok = false;
      break;
      }
    }

  return ok;
}
<|endoftext|>


<commit_before><commit_msg>Do not use FAILED macro when checking return value for Registry APIs.<commit_after><|endoftext|>


<commit_before>// pentago.cpp

#include "pentago.h"

// Quadrants
// AB
// CD

// + clockwise = (default)
// - anti-clockwise = (suffix r)

namespace pentago
{
    static const position A1(0,0);
    static const position A2(0,1);
    static const position A3(0,2);
    static const position A4(0,3);
    static const position A5(0,4);
    static const position A6(0,5);

    static const position B1(1,0);
    static const position B2(1,1);
    static const position B3(1,2);
    static const position B4(1,3);
    static const position B5(1,4);
    static const position B6(1,5);

    static const position C1(2,0);
    static const position C2(2,1);
    static const position C3(2,2);
    static const position C4(2,3);
    static const position C5(2,4);
    static const position C6(2,5);

    static const position D1(3,0);
    static const position D2(3,1);
    static const position D3(3,2);
    static const position D4(3,3);
    static const position D5(3,4);
    static const position D6(3,5);

    static const position E1(4,0);
    static const position E2(4,1);
    static const position E3(4,2);
    static const position E4(4,3);
    static const position E5(4,4);
    static const position E6(4,5);

    static const position F1(5,0);
    static const position F2(5,1);
    static const position F3(5,2);
    static const position F4(5,3);
    static const position F5(5,4);
    static const position F6(5,5);

    // A+
    //   1 2 3 4 5 6
    // A C1B1A1
    // B C2  A2
    // C C3B3A3
    // D
    // E
    // F

    void board_18::transpose(const position & offset)
    {
        // A1 = C1
        state a1 = get(A1+offset);
        setx( A1+offset, get(C1+offset) );

        // A2 = B1
        state a2 = get(A2+offset);
        setx( A2+offset, get(B1+offset) );

        // A3 = A1
        state a3 = get(A3+offset);
        setx( A3+offset, a1 );

        // B1 = C3
        setx( B1+offset, get(C2+offset) );

        // B3 = A2
        state b3 = get(B3+offset);
        setx( B3+offset, a2 );

        // C1 = C3
        setx( C1+offset, get(C3+offset) );

        // C2 = B3
        setx( C2+offset, b3 );

        // C3 = A3
        setx( C3+offset, a3 );
    }

    void board_18::transpose_r(const position & offset)
    {
        // A1 => C1
        state c1 = get(C1+offset);
        setx( C1+offset, get(A1+offset) );

        // A2 => B1
        state b1 = get(B1+offset);
        setx( B1+offset, get(A2+offset) );

        // A3 => A1
        setx( A1+offset, get(A3+offset) );

        // B1 => C2
        state c2 = get(C2+offset);
        setx( C2+offset, b1 );

        // B3 => A2
        setx( A2+offset, get(B3+offset) );

        // C1 => C3
        state c3 = get(C3+offset);
        setx( C3+offset, c1 );

        // C2 => B3
        setx( B3+offset, c2 );

        // C3 => A3
        setx( A3+offset, c3 );
    }

    void board_18::transpose_a()
    {
        transpose( position(0,0) );
    }

    void board_18::transpose_ar()
    {
        transpose_r( position(0,0) );
    }

    // B+
    //   1 2 3 4 5 6
    // A      C4B4A4
    // B      C5  A5
    // C      C6B6A6
    // D
    // E
    // F

    // this is as per A+ but with
    // 1 => 4
    // 2 => 5
    // 3 => 6

    void board_18::transpose_b()
    {
        transpose( position(0,3) );
    }

    void board_18::transpose_br()
    {
        // reverse (anticlockwise) rotation of quadrant B
        transpose_r( position(0,3) );
    }

    // C+
    //   1 2 3 4 5 6
    // A
    // B
    // C
    // D F1E1D1
    // E F2  D2
    // F F3E3D3

    // this is as per A+ but with
    // C => F
    // B => E
    // A => D

    void board_18::transpose_c()
    {
        transpose( position(3,0) );
    }

    void board_18::transpose_cr()
    {
        // reverse (anticlockwise) rotation of quadrant C
        transpose_r( position(3,0) );
    }

    // D+
    //   1 2 3 4 5 6
    // A
    // B
    // C
    // D       F4E4D4
    // E       F5  D5
    // F       F6E5D6

    // this is as per A+ but with
    // C => F, 1 => 4
    // B => E, 2 => 5
    // A => D, 3 => 6

    void board_18::transpose_d()
    {
        transpose( position(3,3) );
    }

    void board_18::transpose_dr()
    {
        // reverse (anticlockwise) rotation of quadrant D
        transpose_r( position(3,3) );
    }

    // Rotational symmetry in the A quadrant:
    //   1 2 3 4 5 6
    // A C3C2C1
    // B B3  B1
    // C A3A2A1
    // D
    // E
    // F
    // returns true if transpose_a == transpose_ar
    bool board_18::symetrical_a() const
    {
        // A1 = C1
        return
            get(A1) == get(C3) &&
            get(A2) == get(C2) &&
            get(A3) == get(C1) &&
            get(B3) == get(B1);
    }

    // Rotational symmetry in the B quadrant:
    // this is as per A but with
    // 1 => 4
    // 2 => 5
    // 3 => 6
    // returns true if transpose_b == transpose_br
    bool board_18::symetrical_b() const
    {
        // A1 = C1
        return
            get(A4) == get(C6) &&
            get(A5) == get(C5) &&
            get(A6) == get(C4) &&
            get(B6) == get(B4);
    }

    // Rotational symmetry in the C quadrant:
    // this is as per A but with
    // C => F
    // B => E
    // A => D
    // returns true if transpose_c == transpose_cr
    bool board_18::symetrical_c() const
    {
        return
            get(D1) == get(F3) &&
            get(D2) == get(F2) &&
            get(D3) == get(F1) &&
            get(E3) == get(E1);
    }

    // Rotational symmetry in the D quadrant:
    // this is as per A+ but with
    // C => F, 1 => 4
    // B => E, 2 => 5
    // A => D, 3 => 6
    // returns true if transpose_c == transpose_cr
    bool board_18::symetrical_d() const
    {
        return
            get(D4) == get(F6) &&
            get(D5) == get(F5) &&
            get(D6) == get(F4) &&
            get(E6) == get(E4);
    }

    state board_18::winningrow(int x)const
    {
        // [012345]
        // [?1234?]
        // winning rows are equal along 1234
        // AND either 0 or 5
        const state r = get(x,1);
        if (r==get(x,2) && r==get(x,3) && r==get(x,4))
            if (r==get(x,0) || r==get(x,5))
                return r;

        return empty;
    }

    state board_18::winningcol(int y)const
    {
        // exactly the same logic as rows, but on the other axis
        const state r = get(1,y);
        if (r==get(2,y) && r==get(3,y) && r==get(4,y))
            if (r==get(0,y) || r==get(5,y))
                return r;

        return empty;
    }

    state board_18::winningdiag()const
    {
        // 6 ways to win on the diag
        // center 0,0-5,5 line
        // + either side of it
        // and 0,5-5,0 line
        // + either side of it

        // both players can win at the same time
        state result = empty;

        // center diagnals have the same logic as rows and columns

        // 0,0-5,5 line
        state r = get(1,1);
        if (r==get(2,2) && r==get(3,3) && r==get(4,4))
            if (r==get(0,0) || r==get(5,5))
                result = (state)(result | r);

        // and 0,5-5,0 line
        r = get(1,4);
        if (r==get(2,3) && r==get(3,2) && r==get(4,1))
            if (r==get(0,5) || r==get(5,0))
                result = (state)(result | r);

        // 0,1-4,5 line
        r = get(A2);
        if (r==get(B3) && r==get(C4) && r==get(D5) && r==get(E6))
            result = (state)(result | r);

        // 1,0-5,4 line
        r = get(B1);
        if (r==get(C2) && r==get(D3) && r==get(E4) && r==get(F5))
            result = (state)(result | r);

        // 0,1-5,0
        r = get(E1);
        if (r==get(D2) && r==get(C3) && r==get(B4) && r==get(A5))
            result = (state)(result | r);

        // 0,4-1,5
        r = get(F2);
        if (r==get(E3) && r==get(D4) && r==get(C5) && r==get(B6))
            result = (state)(result | r);

        return result;
    }

    state board_18::winning()const
    {
        // both players can win at the same time
        state rc = empty, rr = empty;
        for (int n=0;n!=6;++n)
        {
            rr = (state)(rr | winningrow(n));
            rc = (state)(rc | winningcol(n));
        }
        return (state)(rc | rr | winningdiag());
    }

    char tochar( state s )
    {
        switch (s) {
            case pentago::empty:
                return '.';
            case pentago::black:
                return 'X';
            case pentago::white:
                return 'O';
            default:
                return '#';
        }
    }

    state fromchar( char c )
    {
        switch (c) {
            case '.':
                return pentago::empty;
            case 'X':
            case 'x':
                return pentago::black;
            case '0':
            case 'O':
            case 'o':
                return pentago::white;
            default:
                return pentago::invalid;
        }
    }

    board_18 board_18::fromstring( const char* str )
    {
        board result;

        for(int x=0;x!=6;++x)
        {
            for(int y=0;y!=6;++y)
            {
                result.set(position(x,y), fromchar(str[y+x*7]));
            }
        }

        return result;
    }

    std::string tostring( const board& b )
    {
        std::string result;
        result.reserve(7*6);

        for(int x=0;x!=6;++x)
        {
            for(int y=0;y!=6;++y)
            {
                result.push_back( tochar(b.get(x,y)) );
            }
            result.push_back('\n');
        }

        return result;
    }

    std::string tostring_fancy( const board& b )
    {
        std::string result;
        result.reserve(14*8);

        result = "  1 2 3 4 5 6\n";
        for(int x=0;x!=6;++x)
        {
            result.push_back('A'+x);
            for(int y=0;y!=6;++y)
            {
                result += (y==3) ? '|' : ' ';
                result.push_back( tochar(b.get(x,y)) );

            }
            if (x==2)
                result += "\n  -----------";
            result.push_back('\n');
        }

        return result;
    }

    void move::apply(board_18* board, int turn) const
    {
        board->set( mP, turntostate(turn) );
        if (board->winning()==empty)
            mR.apply( board );
    }

    void move::undo(board_18* board) const
    {
        mR.invert().apply( board );
        board->clear( mP );
    }

    move move::fromstring( const char* str )
    {
        position p( toupper(str[0])-'A', str[1]-'1' );
        rotation::quadrant q = (rotation::quadrant) (toupper(str[2])-'A');
        rotation::direction d = (rotation::direction) (str[3]==0 || str[3]=='+' || isspace(str[3]))
            ? rotation::clockwise
            : rotation::anticlockwise;

        move result(p, rotation( q, d));

        return result;
    }

    std::string tostring( const move& b )
    {
        std::string result;
        result.reserve(4);

        result.push_back( 'A'+b.mP.getx() );
        result.push_back( '1'+b.mP.gety() );
        result.push_back( 'A'+b.mR.get_quadrant() );
        result.push_back( (b.mR.get_direction()==rotation::clockwise) ? '+' : '-' );
        return result;
    }

    void empty_positions::next()
    {
        do
        {
            step();
        }while(!finished() && !valid());
    }

    position empty_positions::get()
    {
        return mP;
    }

    bool empty_positions::finished()
    {
        return mP.gety()>=6;
    }

    bool empty_positions::valid()
    {
        return mB.get(mP) == empty;
    }

    void empty_positions::step()
    {
        int x = mP.getx();
        int y = mP.gety();

        x++;
        if (x>5)
        {
            x = 0;
            y++;
        }

        mP.set(x,y);
    }

}<commit_msg>reordered transpose ops to reduce the number of temp copies<commit_after>// pentago.cpp

#include "pentago.h"

// Quadrants
// AB
// CD

// + clockwise = (default)
// - anti-clockwise = (suffix r)

namespace pentago
{
    static const position A1(0,0);
    static const position A2(0,1);
    static const position A3(0,2);
    static const position A4(0,3);
    static const position A5(0,4);
    static const position A6(0,5);

    static const position B1(1,0);
    static const position B2(1,1);
    static const position B3(1,2);
    static const position B4(1,3);
    static const position B5(1,4);
    static const position B6(1,5);

    static const position C1(2,0);
    static const position C2(2,1);
    static const position C3(2,2);
    static const position C4(2,3);
    static const position C5(2,4);
    static const position C6(2,5);

    static const position D1(3,0);
    static const position D2(3,1);
    static const position D3(3,2);
    static const position D4(3,3);
    static const position D5(3,4);
    static const position D6(3,5);

    static const position E1(4,0);
    static const position E2(4,1);
    static const position E3(4,2);
    static const position E4(4,3);
    static const position E5(4,4);
    static const position E6(4,5);

    static const position F1(5,0);
    static const position F2(5,1);
    static const position F3(5,2);
    static const position F4(5,3);
    static const position F5(5,4);
    static const position F6(5,5);

    // A+
    //   1 2 3 4 5 6
    // A C1B1A1
    // B C2  A2
    // C C3B3A3
    // D
    // E
    // F

    void board_18::transpose(const position & offset)
    {
        // A1 = C1
        state a1 = get(A1+offset);
        setx( A1+offset, get(C1+offset) );

        // A2 = B1
        state a2 = get(A2+offset);
        setx( A2+offset, get(B1+offset) );

        // A3 = A1
        state a3 = get(A3+offset);
        setx( A3+offset, a1 );

        // B1 = C2
        setx( B1+offset, get(C2+offset) );

        // C1 = C3
        setx( C1+offset, get(C3+offset) );

        // C2 = B3
        setx( C2+offset, get(B3+offset) );

        // B3 = A2
        setx( B3+offset, a2 );

        // C3 = A3
        setx( C3+offset, a3 );
    }

    void board_18::transpose_r(const position & offset)
    {
        // A1 => C1
        state c1 = get(C1+offset);
        setx( C1+offset, get(A1+offset) );

        // A2 => B1
        state b1 = get(B1+offset);
        setx( B1+offset, get(A2+offset) );

        // A3 => A1
        setx( A1+offset, get(A3+offset) );

        // B1 => C2
        state c2 = get(C2+offset);
        setx( C2+offset, b1 );

        // B3 => A2
        setx( A2+offset, get(B3+offset) );

        // C3 => A3
        setx( A3+offset, get(C3+offset) );

        // C1 => C3
        setx( C3+offset, c1 );

        // C2 => B3
        setx( B3+offset, c2 );
    }

    void board_18::transpose_a()
    {
        transpose( position(0,0) );
    }

    void board_18::transpose_ar()
    {
        transpose_r( position(0,0) );
    }

    // B+
    //   1 2 3 4 5 6
    // A      C4B4A4
    // B      C5  A5
    // C      C6B6A6
    // D
    // E
    // F

    // this is as per A+ but with
    // 1 => 4
    // 2 => 5
    // 3 => 6

    void board_18::transpose_b()
    {
        transpose( position(0,3) );
    }

    void board_18::transpose_br()
    {
        // reverse (anticlockwise) rotation of quadrant B
        transpose_r( position(0,3) );
    }

    // C+
    //   1 2 3 4 5 6
    // A
    // B
    // C
    // D F1E1D1
    // E F2  D2
    // F F3E3D3

    // this is as per A+ but with
    // C => F
    // B => E
    // A => D

    void board_18::transpose_c()
    {
        transpose( position(3,0) );
    }

    void board_18::transpose_cr()
    {
        // reverse (anticlockwise) rotation of quadrant C
        transpose_r( position(3,0) );
    }

    // D+
    //   1 2 3 4 5 6
    // A
    // B
    // C
    // D       F4E4D4
    // E       F5  D5
    // F       F6E5D6

    // this is as per A+ but with
    // C => F, 1 => 4
    // B => E, 2 => 5
    // A => D, 3 => 6

    void board_18::transpose_d()
    {
        transpose( position(3,3) );
    }

    void board_18::transpose_dr()
    {
        // reverse (anticlockwise) rotation of quadrant D
        transpose_r( position(3,3) );
    }

    // Rotational symmetry in the A quadrant:
    //   1 2 3 4 5 6
    // A C3C2C1
    // B B3  B1
    // C A3A2A1
    // D
    // E
    // F
    // returns true if transpose_a == transpose_ar
    bool board_18::symetrical_a() const
    {
        // A1 = C1
        return
            get(A1) == get(C3) &&
            get(A2) == get(C2) &&
            get(A3) == get(C1) &&
            get(B3) == get(B1);
    }

    // Rotational symmetry in the B quadrant:
    // this is as per A but with
    // 1 => 4
    // 2 => 5
    // 3 => 6
    // returns true if transpose_b == transpose_br
    bool board_18::symetrical_b() const
    {
        // A1 = C1
        return
            get(A4) == get(C6) &&
            get(A5) == get(C5) &&
            get(A6) == get(C4) &&
            get(B6) == get(B4);
    }

    // Rotational symmetry in the C quadrant:
    // this is as per A but with
    // C => F
    // B => E
    // A => D
    // returns true if transpose_c == transpose_cr
    bool board_18::symetrical_c() const
    {
        return
            get(D1) == get(F3) &&
            get(D2) == get(F2) &&
            get(D3) == get(F1) &&
            get(E3) == get(E1);
    }

    // Rotational symmetry in the D quadrant:
    // this is as per A+ but with
    // C => F, 1 => 4
    // B => E, 2 => 5
    // A => D, 3 => 6
    // returns true if transpose_c == transpose_cr
    bool board_18::symetrical_d() const
    {
        return
            get(D4) == get(F6) &&
            get(D5) == get(F5) &&
            get(D6) == get(F4) &&
            get(E6) == get(E4);
    }

    state board_18::winningrow(int x)const
    {
        // [012345]
        // [?1234?]
        // winning rows are equal along 1234
        // AND either 0 or 5
        const state r = get(x,1);
        if (r==get(x,2) && r==get(x,3) && r==get(x,4))
            if (r==get(x,0) || r==get(x,5))
                return r;

        return empty;
    }

    state board_18::winningcol(int y)const
    {
        // exactly the same logic as rows, but on the other axis
        const state r = get(1,y);
        if (r==get(2,y) && r==get(3,y) && r==get(4,y))
            if (r==get(0,y) || r==get(5,y))
                return r;

        return empty;
    }

    state board_18::winningdiag()const
    {
        // 6 ways to win on the diag
        // center 0,0-5,5 line
        // + either side of it
        // and 0,5-5,0 line
        // + either side of it

        // both players can win at the same time
        state result = empty;

        // center diagnals have the same logic as rows and columns

        // 0,0-5,5 line
        state r = get(1,1);
        if (r==get(2,2) && r==get(3,3) && r==get(4,4))
            if (r==get(0,0) || r==get(5,5))
                result = (state)(result | r);

        // and 0,5-5,0 line
        r = get(1,4);
        if (r==get(2,3) && r==get(3,2) && r==get(4,1))
            if (r==get(0,5) || r==get(5,0))
                result = (state)(result | r);

        // 0,1-4,5 line
        r = get(A2);
        if (r==get(B3) && r==get(C4) && r==get(D5) && r==get(E6))
            result = (state)(result | r);

        // 1,0-5,4 line
        r = get(B1);
        if (r==get(C2) && r==get(D3) && r==get(E4) && r==get(F5))
            result = (state)(result | r);

        // 0,1-5,0
        r = get(E1);
        if (r==get(D2) && r==get(C3) && r==get(B4) && r==get(A5))
            result = (state)(result | r);

        // 0,4-1,5
        r = get(F2);
        if (r==get(E3) && r==get(D4) && r==get(C5) && r==get(B6))
            result = (state)(result | r);

        return result;
    }

    state board_18::winning()const
    {
        // both players can win at the same time
        state rc = empty, rr = empty;
        for (int n=0;n!=6;++n)
        {
            rr = (state)(rr | winningrow(n));
            rc = (state)(rc | winningcol(n));
        }
        return (state)(rc | rr | winningdiag());
    }

    char tochar( state s )
    {
        switch (s) {
            case pentago::empty:
                return '.';
            case pentago::black:
                return 'X';
            case pentago::white:
                return 'O';
            default:
                return '#';
        }
    }

    state fromchar( char c )
    {
        switch (c) {
            case '.':
                return pentago::empty;
            case 'X':
            case 'x':
                return pentago::black;
            case '0':
            case 'O':
            case 'o':
                return pentago::white;
            default:
                return pentago::invalid;
        }
    }

    board_18 board_18::fromstring( const char* str )
    {
        board result;

        for(int x=0;x!=6;++x)
        {
            for(int y=0;y!=6;++y)
            {
                result.set(position(x,y), fromchar(str[y+x*7]));
            }
        }

        return result;
    }

    std::string tostring( const board& b )
    {
        std::string result;
        result.reserve(7*6);

        for(int x=0;x!=6;++x)
        {
            for(int y=0;y!=6;++y)
            {
                result.push_back( tochar(b.get(x,y)) );
            }
            result.push_back('\n');
        }

        return result;
    }

    std::string tostring_fancy( const board& b )
    {
        std::string result;
        result.reserve(14*8);

        result = "  1 2 3 4 5 6\n";
        for(int x=0;x!=6;++x)
        {
            result.push_back('A'+x);
            for(int y=0;y!=6;++y)
            {
                result += (y==3) ? '|' : ' ';
                result.push_back( tochar(b.get(x,y)) );

            }
            if (x==2)
                result += "\n  -----------";
            result.push_back('\n');
        }

        return result;
    }

    void move::apply(board_18* board, int turn) const
    {
        board->set( mP, turntostate(turn) );
        if (board->winning()==empty)
            mR.apply( board );
    }

    void move::undo(board_18* board) const
    {
        mR.invert().apply( board );
        board->clear( mP );
    }

    move move::fromstring( const char* str )
    {
        position p( toupper(str[0])-'A', str[1]-'1' );
        rotation::quadrant q = (rotation::quadrant) (toupper(str[2])-'A');
        rotation::direction d = (rotation::direction) (str[3]==0 || str[3]=='+' || isspace(str[3]))
            ? rotation::clockwise
            : rotation::anticlockwise;

        move result(p, rotation( q, d));

        return result;
    }

    std::string tostring( const move& b )
    {
        std::string result;
        result.reserve(4);

        result.push_back( 'A'+b.mP.getx() );
        result.push_back( '1'+b.mP.gety() );
        result.push_back( 'A'+b.mR.get_quadrant() );
        result.push_back( (b.mR.get_direction()==rotation::clockwise) ? '+' : '-' );
        return result;
    }

    void empty_positions::next()
    {
        do
        {
            step();
        }while(!finished() && !valid());
    }

    position empty_positions::get()
    {
        return mP;
    }

    bool empty_positions::finished()
    {
        return mP.gety()>=6;
    }

    bool empty_positions::valid()
    {
        return mB.get(mP) == empty;
    }

    void empty_positions::step()
    {
        int x = mP.getx();
        int y = mP.gety();

        x++;
        if (x>5)
        {
            x = 0;
            y++;
        }

        mP.set(x,y);
    }

}<|endoftext|>