<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    "../../Characters/String_Constant.h"
#include    "../../Debug/Trace.h"
#include     "../../Execution/ErrNoException.h"

#include    "InternetAddress.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Memory;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::Network;

#define     qSupportPTONAndPTON_ (qPlatform_POSIX || (qPlatformWindows && (NTDDI_VERSION >= NTDDI_VISTA)))

#if     qCompilerAndStdLib_constexpr_union_variants_Buggy
const   InternetAddress V4::kAddrAny    =   InternetAddress (in_addr {});
const   InternetAddress V6::kAddrAny    =   InternetAddress (in6_addr {});
#if     qPlatform_POSIX
const   InternetAddress V4::kLocalhost  =   InternetAddress (in_addr { INADDR_LOOPBACK } );
#elif   qPlatform_Windows
const   InternetAddress V4::kLocalhost  =   InternetAddress (in_addr { { { 0x1, 0x0, 0x0, 0x7f } } } );
#endif
const   InternetAddress V6::kLocalhost  =   InternetAddress (in6_addr { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } } } );
#endif

#if     qPlatform_Windows
// Not sure why this is necessary, but we get link errors sometimes without it... Maybe a windows makefile issue on regtest apps?
// -- LGP 2014-11-06
#pragma comment(lib, "Ws2_32.lib")
#endif

/*
 ********************************************************************************
 ********************* IO::Network::InternetAddress *****************************
 ********************************************************************************
 */
InternetAddress::InternetAddress (const string& s, AddressFamily af)
    : fAddressFamily_ (AddressFamily::UNKNOWN)
{
    if (not s.empty ()) {
        if (af == AddressFamily::UNKNOWN) {
            // guess format - based on '.' versus ':' in name
            if (s.find ('.') != string::npos) {
                af = AddressFamily::V4;
            }
            else if (s.find (':') != string::npos) {
                af = AddressFamily::V6;
            }
        }
        switch (af) {
            case AddressFamily::V4: {
#if     qSupportPTONAndPTON_
                    Execution::ThrowErrNoIfNegative (inet_pton (AF_INET, s.c_str (), &fV4_));
#elif   qPlatform_Windows
                    DISABLE_COMPILER_MSC_WARNING_START(4996)    // msft doesnt have this on old platforms but still warns!
                    fV4_.s_addr = ::inet_addr (s.c_str ());
                    DISABLE_COMPILER_MSC_WARNING_END(4996)
#else
                    AssertNotImplemented ();
#endif
                    fAddressFamily_ = af;
                }
                break;
            case AddressFamily::V6: {
#if     qSupportPTONAndPTON_
                    Execution::ThrowErrNoIfNegative (inet_pton (AF_INET6, s.c_str (), &fV6_));
#else
                    AssertNotImplemented ();
#endif
                    fAddressFamily_ = af;
                }
                break;
            default: {
                    // @todo need better exception
                    Execution::DoThrow (Execution::StringException (String_Constant (L"Unrecognized address family")));
                }
                break;
        }
    }
}

InternetAddress::InternetAddress (const String& s, AddressFamily af)
    : InternetAddress (s.AsUTF8 (), af)
{
}

namespace   Stroika {
    namespace   Foundation {
        namespace   IO {
            namespace   Network {
                template    <>
                String  InternetAddress::As<String> () const
                {
                    switch (fAddressFamily_) {
                        case AddressFamily::UNKNOWN: {
                                return String ();
                            }
                            break;
                        case AddressFamily::V4: {
#if     qSupportPTONAndPTON_
                                char    buf[INET_ADDRSTRLEN + 1];
                                const char*   result  =   ::inet_ntop (AF_INET, &fV4_, buf, sizeof (buf));
                                return result == nullptr ? String () : String::FromUTF8 (result);
#else
                                DISABLE_COMPILER_MSC_WARNING_START(4996)    // msft doesnt have this on old platforms but still warns!
                                return String::FromUTF8 (::inet_ntoa (fV4_));
                                DISABLE_COMPILER_MSC_WARNING_END(4996)
#endif
                            }
                            break;
                        case AddressFamily::V6: {
#if     qSupportPTONAndPTON_
                                char    buf[INET6_ADDRSTRLEN + 1];
                                const char*   result  =   ::inet_ntop (AF_INET6, &fV6_, buf, sizeof (buf));
                                return result == nullptr ? String () : String::FromUTF8 (result);
#else
                                AssertNotImplemented ();
                                return String ();
#endif
                            }
                            break;
                        default: {
                                RequireNotReached ();
                                return String ();
                            }
                            break;
                    }
                }
            }
        }
    }
}

bool    InternetAddress::IsLocalhostAddress () const
{
    Require (not empty ());
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                // 127.0.0.x
                //return (::ntohl (fV4_.s_addr) & 0xffffff00) == 0x7f000000;
                return (ntohl (fV4_.s_addr) & 0x00ffffff) == 0x00007f;
            }
            break;
        case AddressFamily::V6: {
                return
                    fV6_.s6_addr[0] == 0 and
                    fV6_.s6_addr[1] == 0 and
                    fV6_.s6_addr[2] == 0 and
                    fV6_.s6_addr[3] == 0 and
                    fV6_.s6_addr[4] == 0 and
                    fV6_.s6_addr[5] == 0 and
                    fV6_.s6_addr[6] == 0 and
                    fV6_.s6_addr[7] == 0 and
                    fV6_.s6_addr[8] == 0 and
                    fV6_.s6_addr[9] == 0 and
                    fV6_.s6_addr[10] == 0 and
                    fV6_.s6_addr[11] == 0 and
                    fV6_.s6_addr[12] == 0 and
                    fV6_.s6_addr[13] == 0 and
                    fV6_.s6_addr[14] == 0 and
                    fV6_.s6_addr[15] == 1
                    ;
            }
            break;
    }
    AssertNotReached ();
    return false;
}

bool    InternetAddress::IsLinkLocalAddress () const
{
    Require (not empty ());
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                static  const   InternetAddress kMinLinkLocal_  { "169.254.0.1" };
                static  const   InternetAddress kMaxLinkLocal_  { "169.254.255.254" };
                return kMinLinkLocal_ <= *this and * this <= kMaxLinkLocal_;
            }
            break;
        case AddressFamily::V6: {
                return
                    fV6_.s6_addr[0] == 0xfe and fV6_.s6_addr[1] == 0x80 and
                    fV6_.s6_addr[2] == 0x0 and fV6_.s6_addr[3] == 0x0 and
                    fV6_.s6_addr[4] == 0x0 and fV6_.s6_addr[5] == 0x0 and
                    fV6_.s6_addr[6] == 0x0 and fV6_.s6_addr[7] == 0x0
                    ;
            }
            break;
    }
    AssertNotReached ();
    return false;
}

bool    InternetAddress::IsPrivateAddress () const
{
#if     qDebug && defined (s_net)
    auto ipv4Checker = [](in_addr n) -> bool {
        if (n.s_net == 10)
        {
            return true;
        }
        else if (n.s_net == 172 and (16 <= n.s_host and n.s_host == 31))
        {
            return true;
        }
        else if (n.s_net == 192 and n.s_host == 168)
        {
            return true;
        }
        return false;
    };
#endif
#if     qDebug && defined (s6_words)
    auto ipv6Checker = [](in6_addr n) -> bool {
        return n.s6_words[0] == 0xfc00;
    };
#endif
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                /*
                 * http://www.faqs.org/rfcs/rfc1918.html
                 *
                 *  3. Private Address Space
                 *
                 *      The Internet Assigned Numbers Authority (IANA) has reserved the
                 *      following three blocks of the IP address space for private internets:
                 *
                 *      10.0.0.0        -   10.255.255.255  (10/8 prefix)
                 *      172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
                 *      192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
                 */
                uint32_t    hostByteOrderAddr = ntohl (fV4_.s_addr);
                uint8_t net = (hostByteOrderAddr >> 24);
                uint8_t host = ((hostByteOrderAddr >> 16) & 0xff);
                if (net == 10) {
#if     defined (s_net)
                    Assert (ipv4Checker (fV4_));
#endif
                    return true;
                }
                else if (net == 172 and (16 <= host and host == 31)) {
#if     defined (s_net)
                    Assert (ipv4Checker (fV4_));
#endif
                    return true;
                }
                else if (net == 192 and host == 168) {
#if     defined (s_net)
                    Assert (ipv4Checker (fV4_));
#endif
                    return true;
                }
#if     defined (s_net)
                Assert (not ipv4Checker (fV4_));
#endif
                return false;
            }
            break;
        case AddressFamily::V6: {
                /*
                 *  From http://en.wikipedia.org/wiki/Private_network
                 *
                 *      The concept of private networks and special address reservation for such networks
                 *      has been carried over to the next generation of the Internet Protocol, IPv6.
                 *      The address block fc00:: / 7 has been reserved by IANA as described in RFC 4193.
                 *      These addresses are called Unique Local Addresses (ULA).They are defined as being
                 *      unicast in character and contain a 40 - bit random number in the routing prefix.
                 */
                bool result = fV6_.s6_addr[0] == 0xfc and fV6_.s6_addr[1] == 0x0;
#if     defined (s6_words)
                Assert (ipv6Checker (fV6_) == result);
#endif
                return result;
            }
            break;
    }
    AssertNotReached ();
    return false;
}

bool    InternetAddress::IsMulticastAddress () const
{
    Require (not empty ());
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                // Not sure - might have byte order backwards??? or totally wrong - a bit of a guess?
                return (ntohl (fV4_.s_addr) & 0xf0000000) == 0xe0000000;
            }
            break;
        case AddressFamily::V6: {
                return (fV6_.s6_addr[0] == 0xff);
            }
            break;
    }
    AssertNotReached ();
    return false;
}

int InternetAddress::Compare (const InternetAddress& rhs) const
{
    if (fAddressFamily_ != rhs.fAddressFamily_) {
        return fAddressFamily_ < rhs.fAddressFamily_ ? -1 : 1;
    }
    switch (fAddressFamily_) {
        case AddressFamily::UNKNOWN: {
                return 0;
            }
            break;
        case AddressFamily::V4: {
                // if not equal, compare by net/host before other things so we get sensible intuitive ordering
                if (memcmp (&fV4_, &rhs.fV4_, sizeof (fV4_)) == 0) {
                    return 0;
                }
#if     qPlatform_POSIX
                if (inet_netof (fV4_) != inet_netof (rhs.fV4_)) {
                    return inet_netof (fV4_) - inet_netof (rhs.fV4_);
                }
                if (inet_lnaof (fV4_) != inet_lnaof (rhs.fV4_)) {
                    return inet_lnaof (fV4_) - inet_lnaof (rhs.fV4_);
                }
#elif   qPlatform_Windows
                if (fV4_.s_net != rhs.fV4_.s_net) {
                    return static_cast<int> (fV4_.s_net) - static_cast<int> (rhs.fV4_.s_net);
                }
                if (fV4_.s_host != rhs.fV4_.s_host) {
                    return static_cast<int> (fV4_.s_host) - static_cast<int> (rhs.fV4_.s_host);
                }
                if (fV4_.s_lh != rhs.fV4_.s_lh) {
                    return static_cast<int> (fV4_.s_lh) - static_cast<int> (rhs.fV4_.s_lh);
                }
                if (fV4_.s_impno != rhs.fV4_.s_impno) {
                    return static_cast<int> (fV4_.s_impno) - static_cast<int> (rhs.fV4_.s_impno);
                }
#endif
                AssertNotReached ();
                return 0;
                //return memcmp (&fV4_, &rhs.fV4_, sizeof (fV4_));
            }
            break;
        case AddressFamily::V6: {
                return memcmp (&fV6_, &fV6_, sizeof (fV6_));
            }
            break;
    }
    AssertNotReached ();
    return false;
}
<commit_msg>cast to int for better compare in InternetAddress::Compare () for POSIX<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    "../../Characters/String_Constant.h"
#include    "../../Debug/Trace.h"
#include     "../../Execution/ErrNoException.h"

#include    "InternetAddress.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Memory;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::Network;

#define     qSupportPTONAndPTON_ (qPlatform_POSIX || (qPlatformWindows && (NTDDI_VERSION >= NTDDI_VISTA)))

#if     qCompilerAndStdLib_constexpr_union_variants_Buggy
const   InternetAddress V4::kAddrAny    =   InternetAddress (in_addr {});
const   InternetAddress V6::kAddrAny    =   InternetAddress (in6_addr {});
#if     qPlatform_POSIX
const   InternetAddress V4::kLocalhost  =   InternetAddress (in_addr { INADDR_LOOPBACK } );
#elif   qPlatform_Windows
const   InternetAddress V4::kLocalhost  =   InternetAddress (in_addr { { { 0x1, 0x0, 0x0, 0x7f } } } );
#endif
const   InternetAddress V6::kLocalhost  =   InternetAddress (in6_addr { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } } } );
#endif

#if     qPlatform_Windows
// Not sure why this is necessary, but we get link errors sometimes without it... Maybe a windows makefile issue on regtest apps?
// -- LGP 2014-11-06
#pragma comment(lib, "Ws2_32.lib")
#endif

/*
 ********************************************************************************
 ********************* IO::Network::InternetAddress *****************************
 ********************************************************************************
 */
InternetAddress::InternetAddress (const string& s, AddressFamily af)
    : fAddressFamily_ (AddressFamily::UNKNOWN)
{
    if (not s.empty ()) {
        if (af == AddressFamily::UNKNOWN) {
            // guess format - based on '.' versus ':' in name
            if (s.find ('.') != string::npos) {
                af = AddressFamily::V4;
            }
            else if (s.find (':') != string::npos) {
                af = AddressFamily::V6;
            }
        }
        switch (af) {
            case AddressFamily::V4: {
#if     qSupportPTONAndPTON_
                    Execution::ThrowErrNoIfNegative (inet_pton (AF_INET, s.c_str (), &fV4_));
#elif   qPlatform_Windows
                    DISABLE_COMPILER_MSC_WARNING_START(4996)    // msft doesnt have this on old platforms but still warns!
                    fV4_.s_addr = ::inet_addr (s.c_str ());
                    DISABLE_COMPILER_MSC_WARNING_END(4996)
#else
                    AssertNotImplemented ();
#endif
                    fAddressFamily_ = af;
                }
                break;
            case AddressFamily::V6: {
#if     qSupportPTONAndPTON_
                    Execution::ThrowErrNoIfNegative (inet_pton (AF_INET6, s.c_str (), &fV6_));
#else
                    AssertNotImplemented ();
#endif
                    fAddressFamily_ = af;
                }
                break;
            default: {
                    // @todo need better exception
                    Execution::DoThrow (Execution::StringException (String_Constant (L"Unrecognized address family")));
                }
                break;
        }
    }
}

InternetAddress::InternetAddress (const String& s, AddressFamily af)
    : InternetAddress (s.AsUTF8 (), af)
{
}

namespace   Stroika {
    namespace   Foundation {
        namespace   IO {
            namespace   Network {
                template    <>
                String  InternetAddress::As<String> () const
                {
                    switch (fAddressFamily_) {
                        case AddressFamily::UNKNOWN: {
                                return String ();
                            }
                            break;
                        case AddressFamily::V4: {
#if     qSupportPTONAndPTON_
                                char    buf[INET_ADDRSTRLEN + 1];
                                const char*   result  =   ::inet_ntop (AF_INET, &fV4_, buf, sizeof (buf));
                                return result == nullptr ? String () : String::FromUTF8 (result);
#else
                                DISABLE_COMPILER_MSC_WARNING_START(4996)    // msft doesnt have this on old platforms but still warns!
                                return String::FromUTF8 (::inet_ntoa (fV4_));
                                DISABLE_COMPILER_MSC_WARNING_END(4996)
#endif
                            }
                            break;
                        case AddressFamily::V6: {
#if     qSupportPTONAndPTON_
                                char    buf[INET6_ADDRSTRLEN + 1];
                                const char*   result  =   ::inet_ntop (AF_INET6, &fV6_, buf, sizeof (buf));
                                return result == nullptr ? String () : String::FromUTF8 (result);
#else
                                AssertNotImplemented ();
                                return String ();
#endif
                            }
                            break;
                        default: {
                                RequireNotReached ();
                                return String ();
                            }
                            break;
                    }
                }
            }
        }
    }
}

bool    InternetAddress::IsLocalhostAddress () const
{
    Require (not empty ());
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                // 127.0.0.x
                //return (::ntohl (fV4_.s_addr) & 0xffffff00) == 0x7f000000;
                return (ntohl (fV4_.s_addr) & 0x00ffffff) == 0x00007f;
            }
            break;
        case AddressFamily::V6: {
                return
                    fV6_.s6_addr[0] == 0 and
                    fV6_.s6_addr[1] == 0 and
                    fV6_.s6_addr[2] == 0 and
                    fV6_.s6_addr[3] == 0 and
                    fV6_.s6_addr[4] == 0 and
                    fV6_.s6_addr[5] == 0 and
                    fV6_.s6_addr[6] == 0 and
                    fV6_.s6_addr[7] == 0 and
                    fV6_.s6_addr[8] == 0 and
                    fV6_.s6_addr[9] == 0 and
                    fV6_.s6_addr[10] == 0 and
                    fV6_.s6_addr[11] == 0 and
                    fV6_.s6_addr[12] == 0 and
                    fV6_.s6_addr[13] == 0 and
                    fV6_.s6_addr[14] == 0 and
                    fV6_.s6_addr[15] == 1
                    ;
            }
            break;
    }
    AssertNotReached ();
    return false;
}

bool    InternetAddress::IsLinkLocalAddress () const
{
    Require (not empty ());
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                static  const   InternetAddress kMinLinkLocal_  { "169.254.0.1" };
                static  const   InternetAddress kMaxLinkLocal_  { "169.254.255.254" };
                return kMinLinkLocal_ <= *this and * this <= kMaxLinkLocal_;
            }
            break;
        case AddressFamily::V6: {
                return
                    fV6_.s6_addr[0] == 0xfe and fV6_.s6_addr[1] == 0x80 and
                    fV6_.s6_addr[2] == 0x0 and fV6_.s6_addr[3] == 0x0 and
                    fV6_.s6_addr[4] == 0x0 and fV6_.s6_addr[5] == 0x0 and
                    fV6_.s6_addr[6] == 0x0 and fV6_.s6_addr[7] == 0x0
                    ;
            }
            break;
    }
    AssertNotReached ();
    return false;
}

bool    InternetAddress::IsPrivateAddress () const
{
#if     qDebug && defined (s_net)
    auto ipv4Checker = [](in_addr n) -> bool {
        if (n.s_net == 10)
        {
            return true;
        }
        else if (n.s_net == 172 and (16 <= n.s_host and n.s_host == 31))
        {
            return true;
        }
        else if (n.s_net == 192 and n.s_host == 168)
        {
            return true;
        }
        return false;
    };
#endif
#if     qDebug && defined (s6_words)
    auto ipv6Checker = [](in6_addr n) -> bool {
        return n.s6_words[0] == 0xfc00;
    };
#endif
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                /*
                 * http://www.faqs.org/rfcs/rfc1918.html
                 *
                 *  3. Private Address Space
                 *
                 *      The Internet Assigned Numbers Authority (IANA) has reserved the
                 *      following three blocks of the IP address space for private internets:
                 *
                 *      10.0.0.0        -   10.255.255.255  (10/8 prefix)
                 *      172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
                 *      192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
                 */
                uint32_t    hostByteOrderAddr = ntohl (fV4_.s_addr);
                uint8_t net = (hostByteOrderAddr >> 24);
                uint8_t host = ((hostByteOrderAddr >> 16) & 0xff);
                if (net == 10) {
#if     defined (s_net)
                    Assert (ipv4Checker (fV4_));
#endif
                    return true;
                }
                else if (net == 172 and (16 <= host and host == 31)) {
#if     defined (s_net)
                    Assert (ipv4Checker (fV4_));
#endif
                    return true;
                }
                else if (net == 192 and host == 168) {
#if     defined (s_net)
                    Assert (ipv4Checker (fV4_));
#endif
                    return true;
                }
#if     defined (s_net)
                Assert (not ipv4Checker (fV4_));
#endif
                return false;
            }
            break;
        case AddressFamily::V6: {
                /*
                 *  From http://en.wikipedia.org/wiki/Private_network
                 *
                 *      The concept of private networks and special address reservation for such networks
                 *      has been carried over to the next generation of the Internet Protocol, IPv6.
                 *      The address block fc00:: / 7 has been reserved by IANA as described in RFC 4193.
                 *      These addresses are called Unique Local Addresses (ULA).They are defined as being
                 *      unicast in character and contain a 40 - bit random number in the routing prefix.
                 */
                bool result = fV6_.s6_addr[0] == 0xfc and fV6_.s6_addr[1] == 0x0;
#if     defined (s6_words)
                Assert (ipv6Checker (fV6_) == result);
#endif
                return result;
            }
            break;
    }
    AssertNotReached ();
    return false;
}

bool    InternetAddress::IsMulticastAddress () const
{
    Require (not empty ());
    switch (fAddressFamily_) {
        case AddressFamily::V4: {
                // Not sure - might have byte order backwards??? or totally wrong - a bit of a guess?
                return (ntohl (fV4_.s_addr) & 0xf0000000) == 0xe0000000;
            }
            break;
        case AddressFamily::V6: {
                return (fV6_.s6_addr[0] == 0xff);
            }
            break;
    }
    AssertNotReached ();
    return false;
}

int InternetAddress::Compare (const InternetAddress& rhs) const
{
    if (fAddressFamily_ != rhs.fAddressFamily_) {
        return fAddressFamily_ < rhs.fAddressFamily_ ? -1 : 1;
    }
    switch (fAddressFamily_) {
        case AddressFamily::UNKNOWN: {
                return 0;
            }
            break;
        case AddressFamily::V4: {
                // if not equal, compare by net/host before other things so we get sensible intuitive ordering
                if (memcmp (&fV4_, &rhs.fV4_, sizeof (fV4_)) == 0) {
                    return 0;
                }
#if     qPlatform_POSIX
                if (inet_netof (fV4_) != inet_netof (rhs.fV4_)) {
                    return static_cast<int> (inet_netof (fV4_)) - static_cast<int> (inet_netof (rhs.fV4_));
                }
                if (inet_lnaof (fV4_) != inet_lnaof (rhs.fV4_)) {
                    return static_cast<int> (inet_lnaof (fV4_)) - static_cast<int> (inet_lnaof (rhs.fV4_));
                }
#elif   qPlatform_Windows
                if (fV4_.s_net != rhs.fV4_.s_net) {
                    return static_cast<int> (fV4_.s_net) - static_cast<int> (rhs.fV4_.s_net);
                }
                if (fV4_.s_host != rhs.fV4_.s_host) {
                    return static_cast<int> (fV4_.s_host) - static_cast<int> (rhs.fV4_.s_host);
                }
                if (fV4_.s_lh != rhs.fV4_.s_lh) {
                    return static_cast<int> (fV4_.s_lh) - static_cast<int> (rhs.fV4_.s_lh);
                }
                if (fV4_.s_impno != rhs.fV4_.s_impno) {
                    return static_cast<int> (fV4_.s_impno) - static_cast<int> (rhs.fV4_.s_impno);
                }
#endif
                AssertNotReached ();
                return 0;
                //return memcmp (&fV4_, &rhs.fV4_, sizeof (fV4_));
            }
            break;
        case AddressFamily::V6: {
                return memcmp (&fV6_, &fV6_, sizeof (fV6_));
            }
            break;
    }
    AssertNotReached ();
    return false;
}
<|endoftext|>


<commit_before>#include "Threading.hpp"
#include "ThreadData.hpp"
#include <cassert>
#include <windows.h>

namespace Cpp {
//------------------------------------------------------------------------------
class Win32_ThreadData
{
public:
	Win32_ThreadData()
	{
		InitializeCriticalSection(&cs_);
	}

	~Win32_ThreadData()
	{
		assert(ref_.isNull());
		DeleteCriticalSection(&cs_);
	}

	void lock()
	{
		EnterCriticalSection(&cs);
	}

	void unlock()
	{
		LeaveCriticalSection(&cs);
	}

	void retain()
	{
		ref_.retain();
	}

	void release()
	{
		if(ref_.release())
		{
			delete this;
		}
	}
private:
	AtomicReferenceCounter ref_;
	CRITICAL_SECTION cs_;
};
//------------------------------------------------------------------------------
static DWORD dwTlsIndex = 0;
//------------------------------------------------------------------------------
void Threading::constructProcessData()
{
	assert(!dwTlsIndex);
	dwTlsIndex = TlsAlloc();
	constructThreadData();
}
//------------------------------------------------------------------------------
void Threading::destructProcessData()
{
	destructThreadData();
	assert(dwTlsIndex);
	TlsFree(dwTlsIndex);
}
//------------------------------------------------------------------------------
void Threading::constructThreadData()
{
	assert(dwTlsIndex);
	assert(!TlsGetValue(dwTlsIndex));
	Win32_ThreadData * data = new Win32_ThreadData();
	data->retain();
	LPVOID pvTlsData = reinterpret_cast<LPVOID>(data);
	TlsSetValue(dwTlsIndex, pvTlsData);
}
//------------------------------------------------------------------------------
void Threading::destructThreadData()
{
	assert(dwTlsIndex);
	LPVOID pvTlsData = TlsGetValue(dwTlsIndex);
	assert(pvTlsData);
	Win32_ThreadData * data = reinterpret_cast<Win32_ThreadData*>(pvTlsData);
	data->release();
	TlsSetValue(dwTlsIndex, NULL);
}
//------------------------------------------------------------------------------
Threading::ThreadData * Threading::currentThreadData()
{
	assert(dwTlsIndex);
	LPVOID pvTlsData = TlsGetValue(dwTlsIndex);
	assert(pvTlsData);
	Win32_ThreadData * data = reinterpret_cast<Win32_ThreadData*>(pvTlsData);
	return reinterpret_cast<Threading::ThreadData*>(data);
}
//------------------------------------------------------------------------------
void Threading::ThreadData::lock()
{
	reinterpret_cast<Win32_ThreadData*>(this)->lock();
}
//------------------------------------------------------------------------------
void Threading::ThreadData::unlock()
{
	reinterpret_cast<Win32_ThreadData*>(this)->lock();
}
//------------------------------------------------------------------------------
void Threading::ThreadData::retain()
{
	reinterpret_cast<Win32_ThreadData*>(this)->retain();
}
//------------------------------------------------------------------------------
void Threading::ThreadData::release()
{
	reinterpret_cast<Win32_ThreadData*>(this)->release();
}
//------------------------------------------------------------------------------
} //namespace Cpp<commit_msg>-: Fix for commit 91<commit_after>#include "Threading.hpp"
#include "ThreadData.hpp"
#include <cassert>
#include <windows.h>

namespace Cpp {
//------------------------------------------------------------------------------
class Win32_ThreadData
{
public:
	Win32_ThreadData()
	{
		InitializeCriticalSection(&cs_);
	}

	~Win32_ThreadData()
	{
		assert(ref_.isNull());
		DeleteCriticalSection(&cs_);
	}

	void lock()
	{
		EnterCriticalSection(&cs_);
	}

	void unlock()
	{
		LeaveCriticalSection(&cs_);
	}

	void retain()
	{
		ref_.retain();
	}

	void release()
	{
		if(ref_.release())
		{
			delete this;
		}
	}
private:
	AtomicReferenceCounter ref_;
	CRITICAL_SECTION cs_;
};
//------------------------------------------------------------------------------
static DWORD dwTlsIndex = 0;
//------------------------------------------------------------------------------
void Threading::constructProcessData()
{
	assert(!dwTlsIndex);
	dwTlsIndex = TlsAlloc();
	constructThreadData();
}
//------------------------------------------------------------------------------
void Threading::destructProcessData()
{
	destructThreadData();
	assert(dwTlsIndex);
	TlsFree(dwTlsIndex);
}
//------------------------------------------------------------------------------
void Threading::constructThreadData()
{
	assert(dwTlsIndex);
	assert(!TlsGetValue(dwTlsIndex));
	Win32_ThreadData * data = new Win32_ThreadData();
	data->retain();
	LPVOID pvTlsData = reinterpret_cast<LPVOID>(data);
	TlsSetValue(dwTlsIndex, pvTlsData);
}
//------------------------------------------------------------------------------
void Threading::destructThreadData()
{
	assert(dwTlsIndex);
	LPVOID pvTlsData = TlsGetValue(dwTlsIndex);
	assert(pvTlsData);
	Win32_ThreadData * data = reinterpret_cast<Win32_ThreadData*>(pvTlsData);
	data->release();
	TlsSetValue(dwTlsIndex, NULL);
}
//------------------------------------------------------------------------------
Threading::ThreadData * Threading::currentThreadData()
{
	assert(dwTlsIndex);
	LPVOID pvTlsData = TlsGetValue(dwTlsIndex);
	assert(pvTlsData);
	Win32_ThreadData * data = reinterpret_cast<Win32_ThreadData*>(pvTlsData);
	return reinterpret_cast<Threading::ThreadData*>(data);
}
//------------------------------------------------------------------------------
void Threading::ThreadData::lock()
{
	reinterpret_cast<Win32_ThreadData*>(this)->lock();
}
//------------------------------------------------------------------------------
void Threading::ThreadData::unlock()
{
	reinterpret_cast<Win32_ThreadData*>(this)->lock();
}
//------------------------------------------------------------------------------
void Threading::ThreadData::retain()
{
	reinterpret_cast<Win32_ThreadData*>(this)->retain();
}
//------------------------------------------------------------------------------
void Threading::ThreadData::release()
{
	reinterpret_cast<Win32_ThreadData*>(this)->release();
}
//------------------------------------------------------------------------------
} //namespace Cpp<|endoftext|>


<commit_before>#include <vtkActor.h>
#include <vtkCylinderSource.h>
#include <vtkMath.h>
#include <vtkMinimalStandardRandomSequence.h>
#include <vtkNamedColors.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkOpenVRRenderWindow.h>
#include <vtkOpenVRRenderer.h>
#include <vtkOpenVRRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <array>
#define USER_MATRIX

int main(int, char *[])
{
	vtkSmartPointer<vtkNamedColors> colors =
		vtkSmartPointer<vtkNamedColors>::New();

	// Set the background color.
	std::array<unsigned char, 4> bkg{ { 26, 51, 77, 255 } };
	colors->SetColor("BkgColor", bkg.data());

	// Create a cylinder.
	// Cylinder height vector is (0,1,0).
	// Cylinder center is in the middle of the cylinder
	vtkSmartPointer<vtkCylinderSource> cylinderSource =
		vtkSmartPointer<vtkCylinderSource>::New();
	cylinderSource->SetResolution(15);

	// Generate a random start and end point
	double startPoint[3];
	double endPoint[3];
	vtkSmartPointer<vtkMinimalStandardRandomSequence> rng =
		vtkSmartPointer<vtkMinimalStandardRandomSequence>::New();
	rng->SetSeed(8775070); // For testing.
	for (auto i = 0; i < 3; ++i)
	{
		rng->Next();
		startPoint[i] = rng->GetRangeValue(-10, 10);
		rng->Next();
		endPoint[i] = rng->GetRangeValue(-10, 10);
	}

	// Compute a basis
	double normalizedX[3];
	double normalizedY[3];
	double normalizedZ[3];

	// The X axis is a vector from start to end
	vtkMath::Subtract(endPoint, startPoint, normalizedX);
	double length = vtkMath::Norm(normalizedX);
	vtkMath::Normalize(normalizedX);

	// The Z axis is an arbitrary vector cross X
	double arbitrary[3];
	for (auto i = 0; i < 3; ++i)
	{
		rng->Next();
		arbitrary[i] = rng->GetRangeValue(-10, 10);
	}
	vtkMath::Cross(normalizedX, arbitrary, normalizedZ);
	vtkMath::Normalize(normalizedZ);

	// The Y axis is Z cross X
	vtkMath::Cross(normalizedZ, normalizedX, normalizedY);
	vtkSmartPointer<vtkMatrix4x4> matrix =
		vtkSmartPointer<vtkMatrix4x4>::New();

	// Create the direction cosine matrix
	matrix->Identity();
	for (unsigned int i = 0; i < 3; i++)
	{
		matrix->SetElement(i, 0, normalizedX[i]);
		matrix->SetElement(i, 1, normalizedY[i]);
		matrix->SetElement(i, 2, normalizedZ[i]);
	}

	// Apply the transforms
	vtkSmartPointer<vtkTransform> transform =
		vtkSmartPointer<vtkTransform>::New();
	transform->Translate(startPoint);   // translate to starting point
	transform->Concatenate(matrix);     // apply direction cosines
	transform->RotateZ(-90.0);          // align cylinder to x axis
	transform->Scale(1.0, length, 1.0); // scale along the height vector
	transform->Translate(0, .5, 0);     // translate to start of cylinder

										// Transform the polydata
	vtkSmartPointer<vtkTransformPolyDataFilter> transformPD =
		vtkSmartPointer<vtkTransformPolyDataFilter>::New();
	transformPD->SetTransform(transform);
	transformPD->SetInputConnection(cylinderSource->GetOutputPort());

	//Create a mapper and actor for the cylinder
	vtkSmartPointer<vtkPolyDataMapper> mapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	vtkSmartPointer<vtkActor> actor =
		vtkSmartPointer<vtkActor>::New();
#ifdef USER_MATRIX
	mapper->SetInputConnection(cylinderSource->GetOutputPort());
	actor->SetUserMatrix(transform->GetMatrix());
#else
	mapper->SetInputConnection(transformPD->GetOutputPort());
#endif
	actor->SetMapper(mapper);
	actor->GetProperty()->SetColor(colors->GetColor3d("Cyan").GetData());

	// Create spheres for start and end point
	vtkSmartPointer<vtkSphereSource> sphereStartSource =
		vtkSmartPointer<vtkSphereSource>::New();
	sphereStartSource->SetCenter(startPoint);
	sphereStartSource->SetRadius(0.8);
	vtkSmartPointer<vtkPolyDataMapper> sphereStartMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	sphereStartMapper->SetInputConnection(sphereStartSource->GetOutputPort());
	vtkSmartPointer<vtkActor> sphereStart =
		vtkSmartPointer<vtkActor>::New();
	sphereStart->SetMapper(sphereStartMapper);
	sphereStart->GetProperty()->SetColor(colors->GetColor3d("Yellow").GetData());

	vtkSmartPointer<vtkSphereSource> sphereEndSource =
		vtkSmartPointer<vtkSphereSource>::New();
	sphereEndSource->SetCenter(endPoint);
	sphereEndSource->SetRadius(0.8);
	vtkSmartPointer<vtkPolyDataMapper> sphereEndMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	sphereEndMapper->SetInputConnection(sphereEndSource->GetOutputPort());
	vtkSmartPointer<vtkActor> sphereEnd =
		vtkSmartPointer<vtkActor>::New();
	sphereEnd->SetMapper(sphereEndMapper);
	sphereEnd->GetProperty()->SetColor(colors->GetColor3d("Magenta").GetData());

	//Create a renderer, render window, and interactor
	vtkSmartPointer<vtkOpenVRRenderer> renderer =
		vtkSmartPointer<vtkOpenVRRenderer>::New();
	vtkSmartPointer<vtkOpenVRRenderWindow> renderWindow =
		vtkSmartPointer<vtkOpenVRRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	vtkSmartPointer<vtkOpenVRRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkOpenVRRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	//Add the actor to the scene
	renderer->AddActor(actor);
	renderer->AddActor(sphereStart);
	renderer->AddActor(sphereEnd);
	renderer->SetBackground(colors->GetColor3d("BkgColor").GetData());

	//Render and interact
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}
<commit_msg>Update OpenVROrientedCylinder.cxx<commit_after>#include <vtkActor.h>
#include <vtkCylinderSource.h>
#include <vtkMath.h>
#include <vtkMinimalStandardRandomSequence.h>
#include <vtkNamedColors.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkOpenVRRenderWindow.h>
#include <vtkOpenVRRenderer.h>
#include <vtkOpenVRRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <array>
#define USER_MATRIX

int main(int, char *[])
{
  vtkSmartPointer<vtkNamedColors> colors =
  	vtkSmartPointer<vtkNamedColors>::New();

  // Set the background color.
  std::array<unsigned char, 4> bkg{ { 26, 51, 77, 255 } };
  colors->SetColor("BkgColor", bkg.data());

  // Create a cylinder.
  // Cylinder height vector is (0,1,0).
  // Cylinder center is in the middle of the cylinder
  vtkSmartPointer<vtkCylinderSource> cylinderSource =
  	vtkSmartPointer<vtkCylinderSource>::New();
  cylinderSource->SetResolution(15);

  // Generate a random start and end point
  double startPoint[3];
  double endPoint[3];
  vtkSmartPointer<vtkMinimalStandardRandomSequence> rng =
  	vtkSmartPointer<vtkMinimalStandardRandomSequence>::New();
  rng->SetSeed(8775070); // For testing.
  for (auto i = 0; i < 3; ++i)
  {
  	rng->Next();
  	startPoint[i] = rng->GetRangeValue(-10, 10);
  	rng->Next();
  	endPoint[i] = rng->GetRangeValue(-10, 10);
  }

  // Compute a basis
  double normalizedX[3];
  double normalizedY[3];
  double normalizedZ[3];

  // The X axis is a vector from start to end
  vtkMath::Subtract(endPoint, startPoint, normalizedX);
  double length = vtkMath::Norm(normalizedX);
  vtkMath::Normalize(normalizedX);

  // The Z axis is an arbitrary vector cross X
  double arbitrary[3];
  for (auto i = 0; i < 3; ++i)
  {
  	rng->Next();
  	arbitrary[i] = rng->GetRangeValue(-10, 10);
  }
  vtkMath::Cross(normalizedX, arbitrary, normalizedZ);
  vtkMath::Normalize(normalizedZ);

  // The Y axis is Z cross X
  vtkMath::Cross(normalizedZ, normalizedX, normalizedY);
  vtkSmartPointer<vtkMatrix4x4> matrix =
  	vtkSmartPointer<vtkMatrix4x4>::New();

  // Create the direction cosine matrix
  matrix->Identity();
  for (unsigned int i = 0; i < 3; i++)
  {
  	matrix->SetElement(i, 0, normalizedX[i]);
  	matrix->SetElement(i, 1, normalizedY[i]);
  	matrix->SetElement(i, 2, normalizedZ[i]);
  }

  // Apply the transforms
  vtkSmartPointer<vtkTransform> transform =
  	vtkSmartPointer<vtkTransform>::New();
  transform->Translate(startPoint);   // translate to starting point
  transform->Concatenate(matrix);     // apply direction cosines
  transform->RotateZ(-90.0);          // align cylinder to x axis
  transform->Scale(1.0, length, 1.0); // scale along the height vector
  transform->Translate(0, .5, 0);     // translate to start of cylinder

  									// Transform the polydata
  vtkSmartPointer<vtkTransformPolyDataFilter> transformPD =
  	vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  transformPD->SetTransform(transform);
  transformPD->SetInputConnection(cylinderSource->GetOutputPort());

  //Create a mapper and actor for the cylinder
  vtkSmartPointer<vtkPolyDataMapper> mapper =
  	vtkSmartPointer<vtkPolyDataMapper>::New();
  vtkSmartPointer<vtkActor> actor =
  	vtkSmartPointer<vtkActor>::New();
#ifdef USER_MATRIX
  mapper->SetInputConnection(cylinderSource->GetOutputPort());
  actor->SetUserMatrix(transform->GetMatrix());
#else
  mapper->SetInputConnection(transformPD->GetOutputPort());
#endif
  actor->SetMapper(mapper);
  actor->GetProperty()->SetColor(colors->GetColor3d("Cyan").GetData());

  // Create spheres for start and end point
  vtkSmartPointer<vtkSphereSource> sphereStartSource =
  	vtkSmartPointer<vtkSphereSource>::New();
  sphereStartSource->SetCenter(startPoint);
  sphereStartSource->SetRadius(0.8);
  vtkSmartPointer<vtkPolyDataMapper> sphereStartMapper =
  	vtkSmartPointer<vtkPolyDataMapper>::New();
  sphereStartMapper->SetInputConnection(sphereStartSource->GetOutputPort());
  vtkSmartPointer<vtkActor> sphereStart =
  	vtkSmartPointer<vtkActor>::New();
  sphereStart->SetMapper(sphereStartMapper);
  sphereStart->GetProperty()->SetColor(colors->GetColor3d("Yellow").GetData());

  vtkSmartPointer<vtkSphereSource> sphereEndSource =
  	vtkSmartPointer<vtkSphereSource>::New();
  sphereEndSource->SetCenter(endPoint);
  sphereEndSource->SetRadius(0.8);
  vtkSmartPointer<vtkPolyDataMapper> sphereEndMapper =
  	vtkSmartPointer<vtkPolyDataMapper>::New();
  sphereEndMapper->SetInputConnection(sphereEndSource->GetOutputPort());
  vtkSmartPointer<vtkActor> sphereEnd =
  	vtkSmartPointer<vtkActor>::New();
  sphereEnd->SetMapper(sphereEndMapper);
  sphereEnd->GetProperty()->SetColor(colors->GetColor3d("Magenta").GetData());

  //Create a renderer, render window, and interactor
  vtkSmartPointer<vtkOpenVRRenderer> renderer =
  	vtkSmartPointer<vtkOpenVRRenderer>::New();
  vtkSmartPointer<vtkOpenVRRenderWindow> renderWindow =
  	vtkSmartPointer<vtkOpenVRRenderWindow>::New();
  renderWindow->AddRenderer(renderer);
  vtkSmartPointer<vtkOpenVRRenderWindowInteractor> renderWindowInteractor =
  	vtkSmartPointer<vtkOpenVRRenderWindowInteractor>::New();
  renderWindowInteractor->SetRenderWindow(renderWindow);

  //Add the actor to the scene
  renderer->AddActor(actor);
  renderer->AddActor(sphereStart);
  renderer->AddActor(sphereEnd);
  renderer->SetBackground(colors->GetColor3d("BkgColor").GetData());

  //Render and interact
  renderWindow->Render();
  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////
//                                                                       //
// AliFemtoModelCorrFctn3DSpherical: a class to calculate 3D correlation //
// for pairs of identical particles, binned in spherical coordinates.    //
// In analysis the function should be first created in a macro, then     //
// added to the analysis, and at the end of the macro the procedure to   //
// write out histograms should be called.                                //
//                                                                       //
///////////////////////////////////////////////////////////////////////////

#include "AliFemtoModelCorrFctn3DSpherical.h"
#include "AliFemtoModelManager.h"
#include <TMath.h>
#include <cstdio>

#ifdef __ROOT__
ClassImp(AliFemtoModelCorrFctn3DSpherical)
#endif

//____________________________
AliFemtoModelCorrFctn3DSpherical::AliFemtoModelCorrFctn3DSpherical(char* title, const int& nqbins, const float& QLo, const float& QHi, const int& nphibins, const int& ncthetabins):
  AliFemtoModelCorrFctn(),
  fTrueNumeratorSph(0),
  fFakeNumeratorSph(0),
  fDenominatorSph(0),
  fPairCut(0x0)
{
  // set up numerator
  char tTitNum[100] = "NumTrue";
  strcat(tTitNum,title);
  fTrueNumeratorSph = new TH3D(tTitNum,title,nqbins,QLo,QHi,nphibins,-TMath::Pi(),TMath::Pi(),ncthetabins,-1.0,1.0);
  // set up numerator
  char tTitNumF[100] = "NumFake";
  strcat(tTitNumF,title);
  fFakeNumeratorSph = new TH3D(tTitNumF,title,nqbins,QLo,QHi,nphibins,-TMath::Pi(),TMath::Pi(),ncthetabins,-1.0,1.0);
  // set up denominator
  char tTitDen[100] = "Den";
  strcat(tTitDen,title);
  fDenominatorSph = new TH3D(tTitDen,title,nqbins,QLo,QHi,nphibins,-TMath::Pi(),TMath::Pi(),ncthetabins,-1.0,1.0);

  // to enable error bar calculation...
  fTrueNumeratorSph->Sumw2();
  fFakeNumeratorSph->Sumw2();
  fDenominatorSph->Sumw2();
}

AliFemtoModelCorrFctn3DSpherical::AliFemtoModelCorrFctn3DSpherical(const AliFemtoModelCorrFctn3DSpherical& aCorrFctn) :
  AliFemtoModelCorrFctn(aCorrFctn),
  fTrueNumeratorSph(0),
  fFakeNumeratorSph(0),
  fDenominatorSph(0),
  fPairCut(0x0)
{
  // Copy constructor
  fTrueNumeratorSph = new TH3D(*aCorrFctn.fTrueNumeratorSph);
  fFakeNumeratorSph = new TH3D(*aCorrFctn.fFakeNumeratorSph);
  fDenominatorSph = new TH3D(*aCorrFctn.fDenominatorSph);
  fPairCut = aCorrFctn.fPairCut;
}
//____________________________
AliFemtoModelCorrFctn3DSpherical::~AliFemtoModelCorrFctn3DSpherical(){
  // Destructor
  delete fTrueNumeratorSph;
  delete fFakeNumeratorSph;
  delete fDenominatorSph;
}
//_________________________
AliFemtoModelCorrFctn3DSpherical& AliFemtoModelCorrFctn3DSpherical::operator=(const AliFemtoModelCorrFctn3DSpherical& aCorrFctn)
{
  // assignment operator
  if (this == &aCorrFctn)
    return *this;

  if (fTrueNumeratorSph) delete fTrueNumeratorSph;
  fTrueNumeratorSph = new TH3D(*aCorrFctn.fTrueNumeratorSph);
  if (fFakeNumeratorSph) delete fFakeNumeratorSph;
  fFakeNumeratorSph = new TH3D(*aCorrFctn.fFakeNumeratorSph);
  if (fDenominatorSph) delete fDenominatorSph;
  fDenominatorSph = new TH3D(*aCorrFctn.fDenominatorSph);

  fPairCut = aCorrFctn.fPairCut;

  return *this;
}

//_________________________
void AliFemtoModelCorrFctn3DSpherical::WriteOutHistos(){
  // Write out all histograms to file
  fTrueNumeratorSph->Write();
  fFakeNumeratorSph->Write();
  fDenominatorSph->Write();
}
//______________________________
TList* AliFemtoModelCorrFctn3DSpherical::GetOutputList()
{
  // Prepare the list of objects to be written to the output
  TList *tOutputList = new TList();

  tOutputList->Add(fTrueNumeratorSph);
  tOutputList->Add(fFakeNumeratorSph);
  tOutputList->Add(fDenominatorSph);

  return tOutputList;
}

//_________________________
void AliFemtoModelCorrFctn3DSpherical::Finish(){
  // here is where we should normalize, fit, etc...
}

//____________________________
AliFemtoString AliFemtoModelCorrFctn3DSpherical::Report(){
  // Construct the report
  string stemp = "PRF Frame Spherical 3D Model Correlation Function Report:\n";
  char ctemp[100];
  sprintf(ctemp,"Number of entries in numerator:\t%E\n",fTrueNumeratorSph->GetEntries());
  stemp += ctemp;
  sprintf(ctemp,"Number of entries in denominator:\t%E\n",fDenominatorSph->GetEntries());
  stemp += ctemp;

  if (fPairCut){
    sprintf(ctemp,"Here is the PairCut specific to this CorrFctn\n");
    stemp += ctemp;
    stemp += fPairCut->Report();
  }
  else{
    sprintf(ctemp,"No PairCut specific to this CorrFctn\n");
    stemp += ctemp;
  }

  //
  AliFemtoString returnThis = stemp;
  return returnThis;
}
//____________________________
void AliFemtoModelCorrFctn3DSpherical::AddRealPair( AliFemtoPair* pair){
  // perform operations on real pairs
  if (fPairCut){
    if (!(fPairCut->Pass(pair))) return;
  }

  Double_t weight = fManager->GetWeight(pair);

  double tKO = pair->KOut();
  double tKS = pair->KSide();
  double tKL = pair->KLong();

  double tKR = sqrt(tKO*tKO + tKS*tKS + tKL*tKL);
  double tKC;
  if ( fabs(tKR) < 1e-10 ) tKC = 0.0;
  else tKC=tKL/tKR;
  double tKP=atan2(tKS,tKO);

  fTrueNumeratorSph->Fill(tKR,tKP,tKC,weight);
}
//____________________________
void AliFemtoModelCorrFctn3DSpherical::AddMixedPair( AliFemtoPair* pair){
  // perform operations on mixed pairs
  if (fPairCut){
    if (!(fPairCut->Pass(pair))) return;
  }

  Double_t weight = fManager->GetWeight(pair);

  double tKO = pair->KOut();
  double tKS = pair->KSide();
  double tKL = pair->KLong();

  double tKR = sqrt(tKO*tKO + tKS*tKS + tKL*tKL);
  double tKC;
  if ( fabs(tKR) < 1e-10 ) tKC = 0.0;
  else tKC=tKL/tKR;
  double tKP=atan2(tKS,tKO);

  fFakeNumeratorSph->Fill(tKR,tKP,tKC,weight);
  fDenominatorSph->Fill(tKR,tKP,tKC);
}

<commit_msg>Remove dependence<commit_after>///////////////////////////////////////////////////////////////////////////
//                                                                       //
// AliFemtoModelCorrFctn3DSpherical: a class to calculate 3D correlation //
// for pairs of identical particles, binned in spherical coordinates.    //
// In analysis the function should be first created in a macro, then     //
// added to the analysis, and at the end of the macro the procedure to   //
// write out histograms should be called.                                //
//                                                                       //
///////////////////////////////////////////////////////////////////////////

#include "AliFemtoModelCorrFctn3DSpherical.h"
#include "AliFemtoModelManager.h"
#include <TMath.h>
#include <cstdio>
//#include <Math/SpecFunc.h>

#ifdef __ROOT__
ClassImp(AliFemtoModelCorrFctn3DSpherical)
#endif

//____________________________
AliFemtoModelCorrFctn3DSpherical::AliFemtoModelCorrFctn3DSpherical(char* title, const int& nqbins, const float& QLo, const float& QHi, const int& nphibins, const int& ncthetabins):
  AliFemtoModelCorrFctn(),
  fTrueNumeratorSph(0),
  fFakeNumeratorSph(0),
  fDenominatorSph(0),
  fPairCut(0x0)
{
  // set up numerator
  char tTitNum[100] = "NumTrue";
  strcat(tTitNum,title);
  fTrueNumeratorSph = new TH3D(tTitNum,title,nqbins,QLo,QHi,nphibins,-TMath::Pi(),TMath::Pi(),ncthetabins,-1.0,1.0);
  // set up numerator
  char tTitNumF[100] = "NumFake";
  strcat(tTitNumF,title);
  fFakeNumeratorSph = new TH3D(tTitNumF,title,nqbins,QLo,QHi,nphibins,-TMath::Pi(),TMath::Pi(),ncthetabins,-1.0,1.0);
  // set up denominator
  char tTitDen[100] = "Den";
  strcat(tTitDen,title);
  fDenominatorSph = new TH3D(tTitDen,title,nqbins,QLo,QHi,nphibins,-TMath::Pi(),TMath::Pi(),ncthetabins,-1.0,1.0);

  // to enable error bar calculation...
  fTrueNumeratorSph->Sumw2();
  fFakeNumeratorSph->Sumw2();
  fDenominatorSph->Sumw2();
}

AliFemtoModelCorrFctn3DSpherical::AliFemtoModelCorrFctn3DSpherical(const AliFemtoModelCorrFctn3DSpherical& aCorrFctn) :
  AliFemtoModelCorrFctn(aCorrFctn),
  fTrueNumeratorSph(0),
  fFakeNumeratorSph(0),
  fDenominatorSph(0),
  fPairCut(0x0)
{
  // Copy constructor
  fTrueNumeratorSph = new TH3D(*aCorrFctn.fTrueNumeratorSph);
  fFakeNumeratorSph = new TH3D(*aCorrFctn.fFakeNumeratorSph);
  fDenominatorSph = new TH3D(*aCorrFctn.fDenominatorSph);
  fPairCut = aCorrFctn.fPairCut;
}
//____________________________
AliFemtoModelCorrFctn3DSpherical::~AliFemtoModelCorrFctn3DSpherical(){
  // Destructor
  delete fTrueNumeratorSph;
  delete fFakeNumeratorSph;
  delete fDenominatorSph;
}
//_________________________
AliFemtoModelCorrFctn3DSpherical& AliFemtoModelCorrFctn3DSpherical::operator=(const AliFemtoModelCorrFctn3DSpherical& aCorrFctn)
{
  // assignment operator
  if (this == &aCorrFctn)
    return *this;

  if (fTrueNumeratorSph) delete fTrueNumeratorSph;
  fTrueNumeratorSph = new TH3D(*aCorrFctn.fTrueNumeratorSph);
  if (fFakeNumeratorSph) delete fFakeNumeratorSph;
  fFakeNumeratorSph = new TH3D(*aCorrFctn.fFakeNumeratorSph);
  if (fDenominatorSph) delete fDenominatorSph;
  fDenominatorSph = new TH3D(*aCorrFctn.fDenominatorSph);

  fPairCut = aCorrFctn.fPairCut;

  return *this;
}

//_________________________
void AliFemtoModelCorrFctn3DSpherical::WriteOutHistos(){
  // Write out all histograms to file
  fTrueNumeratorSph->Write();
  fFakeNumeratorSph->Write();
  fDenominatorSph->Write();
}
//______________________________
TList* AliFemtoModelCorrFctn3DSpherical::GetOutputList()
{
  // Prepare the list of objects to be written to the output
  TList *tOutputList = new TList();

  tOutputList->Add(fTrueNumeratorSph);
  tOutputList->Add(fFakeNumeratorSph);
  tOutputList->Add(fDenominatorSph);

  return tOutputList;
}

//_________________________
void AliFemtoModelCorrFctn3DSpherical::Finish(){
  // here is where we should normalize, fit, etc...
}

//____________________________
AliFemtoString AliFemtoModelCorrFctn3DSpherical::Report(){
  // Construct the report
  string stemp = "PRF Frame Spherical 3D Model Correlation Function Report:\n";
  char ctemp[100];
  sprintf(ctemp,"Number of entries in numerator:\t%E\n",fTrueNumeratorSph->GetEntries());
  stemp += ctemp;
  sprintf(ctemp,"Number of entries in denominator:\t%E\n",fDenominatorSph->GetEntries());
  stemp += ctemp;

  if (fPairCut){
    sprintf(ctemp,"Here is the PairCut specific to this CorrFctn\n");
    stemp += ctemp;
    stemp += fPairCut->Report();
  }
  else{
    sprintf(ctemp,"No PairCut specific to this CorrFctn\n");
    stemp += ctemp;
  }

  //
  AliFemtoString returnThis = stemp;
  return returnThis;
}
//____________________________
void AliFemtoModelCorrFctn3DSpherical::AddRealPair( AliFemtoPair* pair){
  // perform operations on real pairs
  if (fPairCut){
    if (!(fPairCut->Pass(pair))) return;
  }

  Double_t weight = fManager->GetWeight(pair);

  double tKO = pair->KOut();
  double tKS = pair->KSide();
  double tKL = pair->KLong();

  double tKR = sqrt(tKO*tKO + tKS*tKS + tKL*tKL);
  double tKC;
  if ( fabs(tKR) < 1e-10 ) tKC = 0.0;
  else tKC=tKL/tKR;
  double tKP=atan2(tKS,tKO);

  fTrueNumeratorSph->Fill(tKR,tKP,tKC,weight);
}
//____________________________
void AliFemtoModelCorrFctn3DSpherical::AddMixedPair( AliFemtoPair* pair){
  // perform operations on mixed pairs
  if (fPairCut){
    if (!(fPairCut->Pass(pair))) return;
  }

  Double_t weight = fManager->GetWeight(pair);

  double tKO = pair->KOut();
  double tKS = pair->KSide();
  double tKL = pair->KLong();

  double tKR = sqrt(tKO*tKO + tKS*tKS + tKL*tKL);
  double tKC;
  if ( fabs(tKR) < 1e-10 ) tKC = 0.0;
  else tKC=tKL/tKR;
  double tKP=atan2(tKS,tKO);

  fFakeNumeratorSph->Fill(tKR,tKP,tKC,weight);
  fDenominatorSph->Fill(tKR,tKP,tKC);
}

<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/consteval.h"
#include "kernel/celltypes.h"
#include "fsmdata.h"
#include <string.h>

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct FsmOpt
{
	FsmData fsm_data;
	RTLIL::Cell *cell;
	RTLIL::Module *module;

	void opt_unreachable_states()
	{
		while (1)
		{
			std::set<int> unreachable_states;
			std::vector<FsmData::transition_t> new_transition_table;
			std::vector<RTLIL::Const> new_state_table;
			std::map<int, int> old_to_new_state;

			for (int i = 0; i < GetSize(fsm_data.state_table); i++)
				if (i != fsm_data.reset_state)
					unreachable_states.insert(i);

			for (auto &trans : fsm_data.transition_table)
				unreachable_states.erase(trans.state_out);

			if (unreachable_states.empty())
				break;

			for (int i = 0; i < GetSize(fsm_data.state_table); i++) {
				if (unreachable_states.count(i)) {
					log("  Removing unreachable state %s.\n", log_signal(fsm_data.state_table[i]));
					continue;
				}
				old_to_new_state[i] = GetSize(new_state_table);
				new_state_table.push_back(fsm_data.state_table[i]);
			}

			for (auto trans : fsm_data.transition_table) {
				if (unreachable_states.count(trans.state_in))
					continue;
				trans.state_in = old_to_new_state.at(trans.state_in);
				trans.state_out = old_to_new_state.at(trans.state_out);
				new_transition_table.push_back(trans);
			}

			new_transition_table.swap(fsm_data.transition_table);
			new_state_table.swap(fsm_data.state_table);
			fsm_data.reset_state = old_to_new_state.at(fsm_data.reset_state);
		}
	}

	bool signal_is_unused(RTLIL::SigSpec sig)
	{
		RTLIL::SigBit bit = sig.as_bit();

		if (bit.wire == NULL || bit.wire->attributes.count("\\unused_bits") == 0)
			return false;

		char *str = strdup(bit.wire->attributes["\\unused_bits"].decode_string().c_str());
		for (char *tok = strtok(str, " "); tok != NULL; tok = strtok(NULL, " ")) {
			if (tok[0] && bit.offset == atoi(tok)) {
				free(str);
				return true;
			}
		}
		free(str);

		return false;
	}

	void opt_const_and_unused_inputs()
	{
		RTLIL::SigSpec ctrl_in = cell->getPort("\\CTRL_IN");
		std::vector<bool> ctrl_in_used(ctrl_in.size());

		std::vector<FsmData::transition_t> new_transition_table;
		for (auto &tr : fsm_data.transition_table) {
			for (int i = 0; i < ctrl_in.size(); i++) {
				RTLIL::SigSpec ctrl_bit = ctrl_in.extract(i, 1);
				if (ctrl_bit.is_fully_const()) {
					if (tr.ctrl_in.bits[i] <= RTLIL::State::S1 && RTLIL::SigSpec(tr.ctrl_in.bits[i]) != ctrl_bit)
						goto delete_this_transition;
					continue;
				}
				if (tr.ctrl_in.bits[i] <= RTLIL::State::S1)
					ctrl_in_used[i] = true;
			}
			new_transition_table.push_back(tr);
		delete_this_transition:;
		}

		for (int i = int(ctrl_in_used.size())-1; i >= 0; i--) {
			if (!ctrl_in_used[i]) {
				log("  Removing unused input signal %s.\n", log_signal(cell->getPort("\\CTRL_IN").extract(i, 1)));
				for (auto &tr : new_transition_table) {
					RTLIL::SigSpec tmp(tr.ctrl_in);
					tmp.remove(i, 1);
					tr.ctrl_in = tmp.as_const();
				}
				RTLIL::SigSpec new_ctrl_in = cell->getPort("\\CTRL_IN");
				new_ctrl_in.remove(i, 1);
				cell->setPort("\\CTRL_IN", new_ctrl_in);
				fsm_data.num_inputs--;
			}
		}

		fsm_data.transition_table.swap(new_transition_table);
		new_transition_table.clear();
	}

	void opt_unused_outputs()
	{
		for (int i = 0; i < fsm_data.num_outputs; i++) {
			RTLIL::SigSpec sig = cell->getPort("\\CTRL_OUT").extract(i, 1);
			if (signal_is_unused(sig)) {
				log("  Removing unused output signal %s.\n", log_signal(sig));
				RTLIL::SigSpec new_ctrl_out = cell->getPort("\\CTRL_OUT");
				new_ctrl_out.remove(i, 1);
				cell->setPort("\\CTRL_OUT", new_ctrl_out);
				for (auto &tr : fsm_data.transition_table) {
					RTLIL::SigSpec tmp(tr.ctrl_out);
					tmp.remove(i, 1);
					tr.ctrl_out = tmp.as_const();
				}
				fsm_data.num_outputs--;
				i--;
			}
		}
	}

	void opt_alias_inputs()
	{
		RTLIL::SigSpec &ctrl_in = cell->connections_["\\CTRL_IN"];

		for (int i = 0; i < ctrl_in.size(); i++)
		for (int j = i+1; j < ctrl_in.size(); j++)
			if (ctrl_in.extract(i, 1) == ctrl_in.extract(j, 1))
			{
				log("  Optimize handling of signal %s that is connected to inputs %d and %d.\n", log_signal(ctrl_in.extract(i, 1)), i, j);
				std::vector<FsmData::transition_t> new_transition_table;

				for (auto tr : fsm_data.transition_table)
				{
					RTLIL::State &si = tr.ctrl_in.bits[i];
					RTLIL::State &sj = tr.ctrl_in.bits[j];

					if (si > RTLIL::State::S1)
						si = sj;
					else if (sj > RTLIL::State::S1)
						sj = si;

					if (si == sj) {
						RTLIL::SigSpec tmp(tr.ctrl_in);
						tmp.remove(j, 1);
						tr.ctrl_in = tmp.as_const();
						new_transition_table.push_back(tr);
					}
				}

				ctrl_in.remove(j--, 1);
				fsm_data.num_inputs--;

				fsm_data.transition_table.swap(new_transition_table);
				new_transition_table.clear();
			}
	}

	void opt_feedback_inputs()
	{
		RTLIL::SigSpec &ctrl_in = cell->connections_["\\CTRL_IN"];
		RTLIL::SigSpec &ctrl_out = cell->connections_["\\CTRL_OUT"];

		for (int j = 0; j < ctrl_out.size(); j++)
		for (int i = 0; i < ctrl_in.size(); i++)
			if (ctrl_in.extract(i, 1) == ctrl_out.extract(j, 1))
			{
				log("  Optimize handling of signal %s that is connected to input %d and output %d.\n", log_signal(ctrl_in.extract(i, 1)), i, j);
				std::vector<FsmData::transition_t> new_transition_table;

				for (auto tr : fsm_data.transition_table)
				{
					RTLIL::State &si = tr.ctrl_in.bits[i];
					RTLIL::State &sj = tr.ctrl_out.bits[j];

					if (si > RTLIL::State::S1 || si == sj) {
						RTLIL::SigSpec tmp(tr.ctrl_in);
						tmp.remove(i, 1);
						tr.ctrl_in = tmp.as_const();
						new_transition_table.push_back(tr);
					}
				}

				ctrl_in.remove(i--, 1);
				fsm_data.num_inputs--;

				fsm_data.transition_table.swap(new_transition_table);
				new_transition_table.clear();
			}
	}

	void opt_find_dont_care_worker(std::set<RTLIL::Const> &set, int bit, FsmData::transition_t &tr, bool &did_something)
	{
		std::set<RTLIL::Const> new_set;

		for (auto &pattern : set)
		{
			if (pattern.bits[bit] > RTLIL::State::S1) {
				new_set.insert(pattern);
				continue;
			}

			RTLIL::Const other_pattern = pattern;

			if (pattern.bits[bit] == RTLIL::State::S1)
				other_pattern.bits[bit] = RTLIL::State::S0;
			else
				other_pattern.bits[bit] = RTLIL::State::S1;

			if (set.count(other_pattern) > 0) {
				log("  Merging pattern %s and %s from group (%d %d %s).\n", log_signal(pattern), log_signal(other_pattern),
						tr.state_in, tr.state_out, log_signal(tr.ctrl_out));
				other_pattern.bits[bit] = RTLIL::State::Sa;
				new_set.insert(other_pattern);
				did_something = true;
				continue;
			}

			new_set.insert(pattern);
		}

		set.swap(new_set);
	}

	void opt_find_dont_care()
	{
		typedef std::pair<std::pair<int, int>, RTLIL::Const> group_t;
		std::map<group_t, std::set<RTLIL::Const>> transitions_by_group;

		for (auto &tr : fsm_data.transition_table) {
			group_t group(std::pair<int, int>(tr.state_in, tr.state_out), tr.ctrl_out);
			transitions_by_group[group].insert(tr.ctrl_in);
		}

		fsm_data.transition_table.clear();
		for (auto &it : transitions_by_group)
		{
			FsmData::transition_t tr;
			tr.state_in = it.first.first.first;
			tr.state_out = it.first.first.second;
			tr.ctrl_out = it.first.second;

			bool did_something = true;
			while (did_something) {
				did_something = false;
				for (int i = 0; i < fsm_data.num_inputs; i++)
					opt_find_dont_care_worker(it.second, i, tr, did_something);
			}

			for (auto &ci : it.second) {
				tr.ctrl_in = ci;
				fsm_data.transition_table.push_back(tr);
			}
		}
	}

	FsmOpt(RTLIL::Cell *cell, RTLIL::Module *module)
	{
		log("Optimizing FSM `%s' from module `%s'.\n", cell->name.c_str(), module->name.c_str());

		fsm_data.copy_from_cell(cell);
		this->cell = cell;
		this->module = module;

		opt_unreachable_states();

		opt_unused_outputs();

		opt_alias_inputs();
		opt_feedback_inputs();
		opt_find_dont_care();

		opt_const_and_unused_inputs();

		fsm_data.copy_to_cell(cell);
	}
};

PRIVATE_NAMESPACE_END

void YOSYS_NAMESPACE_PREFIX FsmData::optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module)
{
	FsmOpt fsmopt(cell, module);
}

PRIVATE_NAMESPACE_BEGIN

struct FsmOptPass : public Pass {
	FsmOptPass() : Pass("fsm_opt", "optimize finite state machines") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    fsm_opt [selection]\n");
		log("\n");
		log("This pass optimizes FSM cells. It detects which output signals are actually\n");
		log("not used and removes them from the FSM. This pass is usually used in\n");
		log("combination with the 'opt_clean' pass (see also 'help fsm').\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n");
		extra_args(args, 1, design);

		for (auto &mod_it : design->modules_) {
			if (design->selected(mod_it.second))
				for (auto &cell_it : mod_it.second->cells_)
					if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second))
						FsmData::optimize_fsm(cell_it.second, mod_it.second);
		}
	}
} FsmOptPass;

PRIVATE_NAMESPACE_END
<commit_msg>fsm_opt: Fix runtime error for FSMs without a reset state<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/consteval.h"
#include "kernel/celltypes.h"
#include "fsmdata.h"
#include <string.h>

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct FsmOpt
{
	FsmData fsm_data;
	RTLIL::Cell *cell;
	RTLIL::Module *module;

	void opt_unreachable_states()
	{
		while (1)
		{
			std::set<int> unreachable_states;
			std::vector<FsmData::transition_t> new_transition_table;
			std::vector<RTLIL::Const> new_state_table;
			std::map<int, int> old_to_new_state;

			for (int i = 0; i < GetSize(fsm_data.state_table); i++)
				if (i != fsm_data.reset_state)
					unreachable_states.insert(i);

			for (auto &trans : fsm_data.transition_table)
				unreachable_states.erase(trans.state_out);

			if (unreachable_states.empty())
				break;

			for (int i = 0; i < GetSize(fsm_data.state_table); i++) {
				if (unreachable_states.count(i)) {
					log("  Removing unreachable state %s.\n", log_signal(fsm_data.state_table[i]));
					continue;
				}
				old_to_new_state[i] = GetSize(new_state_table);
				new_state_table.push_back(fsm_data.state_table[i]);
			}

			for (auto trans : fsm_data.transition_table) {
				if (unreachable_states.count(trans.state_in))
					continue;
				trans.state_in = old_to_new_state.at(trans.state_in);
				trans.state_out = old_to_new_state.at(trans.state_out);
				new_transition_table.push_back(trans);
			}

			new_transition_table.swap(fsm_data.transition_table);
			new_state_table.swap(fsm_data.state_table);
			if (fsm_data.reset_state != -1)
				fsm_data.reset_state = old_to_new_state.at(fsm_data.reset_state);
		}
	}

	bool signal_is_unused(RTLIL::SigSpec sig)
	{
		RTLIL::SigBit bit = sig.as_bit();

		if (bit.wire == NULL || bit.wire->attributes.count("\\unused_bits") == 0)
			return false;

		char *str = strdup(bit.wire->attributes["\\unused_bits"].decode_string().c_str());
		for (char *tok = strtok(str, " "); tok != NULL; tok = strtok(NULL, " ")) {
			if (tok[0] && bit.offset == atoi(tok)) {
				free(str);
				return true;
			}
		}
		free(str);

		return false;
	}

	void opt_const_and_unused_inputs()
	{
		RTLIL::SigSpec ctrl_in = cell->getPort("\\CTRL_IN");
		std::vector<bool> ctrl_in_used(ctrl_in.size());

		std::vector<FsmData::transition_t> new_transition_table;
		for (auto &tr : fsm_data.transition_table) {
			for (int i = 0; i < ctrl_in.size(); i++) {
				RTLIL::SigSpec ctrl_bit = ctrl_in.extract(i, 1);
				if (ctrl_bit.is_fully_const()) {
					if (tr.ctrl_in.bits[i] <= RTLIL::State::S1 && RTLIL::SigSpec(tr.ctrl_in.bits[i]) != ctrl_bit)
						goto delete_this_transition;
					continue;
				}
				if (tr.ctrl_in.bits[i] <= RTLIL::State::S1)
					ctrl_in_used[i] = true;
			}
			new_transition_table.push_back(tr);
		delete_this_transition:;
		}

		for (int i = int(ctrl_in_used.size())-1; i >= 0; i--) {
			if (!ctrl_in_used[i]) {
				log("  Removing unused input signal %s.\n", log_signal(cell->getPort("\\CTRL_IN").extract(i, 1)));
				for (auto &tr : new_transition_table) {
					RTLIL::SigSpec tmp(tr.ctrl_in);
					tmp.remove(i, 1);
					tr.ctrl_in = tmp.as_const();
				}
				RTLIL::SigSpec new_ctrl_in = cell->getPort("\\CTRL_IN");
				new_ctrl_in.remove(i, 1);
				cell->setPort("\\CTRL_IN", new_ctrl_in);
				fsm_data.num_inputs--;
			}
		}

		fsm_data.transition_table.swap(new_transition_table);
		new_transition_table.clear();
	}

	void opt_unused_outputs()
	{
		for (int i = 0; i < fsm_data.num_outputs; i++) {
			RTLIL::SigSpec sig = cell->getPort("\\CTRL_OUT").extract(i, 1);
			if (signal_is_unused(sig)) {
				log("  Removing unused output signal %s.\n", log_signal(sig));
				RTLIL::SigSpec new_ctrl_out = cell->getPort("\\CTRL_OUT");
				new_ctrl_out.remove(i, 1);
				cell->setPort("\\CTRL_OUT", new_ctrl_out);
				for (auto &tr : fsm_data.transition_table) {
					RTLIL::SigSpec tmp(tr.ctrl_out);
					tmp.remove(i, 1);
					tr.ctrl_out = tmp.as_const();
				}
				fsm_data.num_outputs--;
				i--;
			}
		}
	}

	void opt_alias_inputs()
	{
		RTLIL::SigSpec &ctrl_in = cell->connections_["\\CTRL_IN"];

		for (int i = 0; i < ctrl_in.size(); i++)
		for (int j = i+1; j < ctrl_in.size(); j++)
			if (ctrl_in.extract(i, 1) == ctrl_in.extract(j, 1))
			{
				log("  Optimize handling of signal %s that is connected to inputs %d and %d.\n", log_signal(ctrl_in.extract(i, 1)), i, j);
				std::vector<FsmData::transition_t> new_transition_table;

				for (auto tr : fsm_data.transition_table)
				{
					RTLIL::State &si = tr.ctrl_in.bits[i];
					RTLIL::State &sj = tr.ctrl_in.bits[j];

					if (si > RTLIL::State::S1)
						si = sj;
					else if (sj > RTLIL::State::S1)
						sj = si;

					if (si == sj) {
						RTLIL::SigSpec tmp(tr.ctrl_in);
						tmp.remove(j, 1);
						tr.ctrl_in = tmp.as_const();
						new_transition_table.push_back(tr);
					}
				}

				ctrl_in.remove(j--, 1);
				fsm_data.num_inputs--;

				fsm_data.transition_table.swap(new_transition_table);
				new_transition_table.clear();
			}
	}

	void opt_feedback_inputs()
	{
		RTLIL::SigSpec &ctrl_in = cell->connections_["\\CTRL_IN"];
		RTLIL::SigSpec &ctrl_out = cell->connections_["\\CTRL_OUT"];

		for (int j = 0; j < ctrl_out.size(); j++)
		for (int i = 0; i < ctrl_in.size(); i++)
			if (ctrl_in.extract(i, 1) == ctrl_out.extract(j, 1))
			{
				log("  Optimize handling of signal %s that is connected to input %d and output %d.\n", log_signal(ctrl_in.extract(i, 1)), i, j);
				std::vector<FsmData::transition_t> new_transition_table;

				for (auto tr : fsm_data.transition_table)
				{
					RTLIL::State &si = tr.ctrl_in.bits[i];
					RTLIL::State &sj = tr.ctrl_out.bits[j];

					if (si > RTLIL::State::S1 || si == sj) {
						RTLIL::SigSpec tmp(tr.ctrl_in);
						tmp.remove(i, 1);
						tr.ctrl_in = tmp.as_const();
						new_transition_table.push_back(tr);
					}
				}

				ctrl_in.remove(i--, 1);
				fsm_data.num_inputs--;

				fsm_data.transition_table.swap(new_transition_table);
				new_transition_table.clear();
			}
	}

	void opt_find_dont_care_worker(std::set<RTLIL::Const> &set, int bit, FsmData::transition_t &tr, bool &did_something)
	{
		std::set<RTLIL::Const> new_set;

		for (auto &pattern : set)
		{
			if (pattern.bits[bit] > RTLIL::State::S1) {
				new_set.insert(pattern);
				continue;
			}

			RTLIL::Const other_pattern = pattern;

			if (pattern.bits[bit] == RTLIL::State::S1)
				other_pattern.bits[bit] = RTLIL::State::S0;
			else
				other_pattern.bits[bit] = RTLIL::State::S1;

			if (set.count(other_pattern) > 0) {
				log("  Merging pattern %s and %s from group (%d %d %s).\n", log_signal(pattern), log_signal(other_pattern),
						tr.state_in, tr.state_out, log_signal(tr.ctrl_out));
				other_pattern.bits[bit] = RTLIL::State::Sa;
				new_set.insert(other_pattern);
				did_something = true;
				continue;
			}

			new_set.insert(pattern);
		}

		set.swap(new_set);
	}

	void opt_find_dont_care()
	{
		typedef std::pair<std::pair<int, int>, RTLIL::Const> group_t;
		std::map<group_t, std::set<RTLIL::Const>> transitions_by_group;

		for (auto &tr : fsm_data.transition_table) {
			group_t group(std::pair<int, int>(tr.state_in, tr.state_out), tr.ctrl_out);
			transitions_by_group[group].insert(tr.ctrl_in);
		}

		fsm_data.transition_table.clear();
		for (auto &it : transitions_by_group)
		{
			FsmData::transition_t tr;
			tr.state_in = it.first.first.first;
			tr.state_out = it.first.first.second;
			tr.ctrl_out = it.first.second;

			bool did_something = true;
			while (did_something) {
				did_something = false;
				for (int i = 0; i < fsm_data.num_inputs; i++)
					opt_find_dont_care_worker(it.second, i, tr, did_something);
			}

			for (auto &ci : it.second) {
				tr.ctrl_in = ci;
				fsm_data.transition_table.push_back(tr);
			}
		}
	}

	FsmOpt(RTLIL::Cell *cell, RTLIL::Module *module)
	{
		log("Optimizing FSM `%s' from module `%s'.\n", cell->name.c_str(), module->name.c_str());

		fsm_data.copy_from_cell(cell);
		this->cell = cell;
		this->module = module;

		opt_unreachable_states();

		opt_unused_outputs();

		opt_alias_inputs();
		opt_feedback_inputs();
		opt_find_dont_care();

		opt_const_and_unused_inputs();

		fsm_data.copy_to_cell(cell);
	}
};

PRIVATE_NAMESPACE_END

void YOSYS_NAMESPACE_PREFIX FsmData::optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module)
{
	FsmOpt fsmopt(cell, module);
}

PRIVATE_NAMESPACE_BEGIN

struct FsmOptPass : public Pass {
	FsmOptPass() : Pass("fsm_opt", "optimize finite state machines") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    fsm_opt [selection]\n");
		log("\n");
		log("This pass optimizes FSM cells. It detects which output signals are actually\n");
		log("not used and removes them from the FSM. This pass is usually used in\n");
		log("combination with the 'opt_clean' pass (see also 'help fsm').\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n");
		extra_args(args, 1, design);

		for (auto &mod_it : design->modules_) {
			if (design->selected(mod_it.second))
				for (auto &cell_it : mod_it.second->cells_)
					if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second))
						FsmData::optimize_fsm(cell_it.second, mod_it.second);
		}
	}
} FsmOptPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/*!
	@file
	@author		George Evmenov
	@date		07/2009
*/

#include "MyGUI_OpenGLRenderManager.h"
#include "MyGUI_OpenGLTexture.h"
#include "MyGUI_OpenGLVertexBuffer.h"
#include "MyGUI_OpenGLDiagnostic.h"
#include "MyGUI_VertexData.h"
#include "MyGUI_Gui.h"
#include "MyGUI_Timer.h"

#include "GL/glew.h"

namespace MyGUI
{

	OpenGLRenderManager::OpenGLRenderManager() :
		mUpdate(false),
		mImageLoader(nullptr),
		mPboIsSupported(false),
		mIsInitialise(false)
	{
	}

	void OpenGLRenderManager::initialise(OpenGLImageLoader* _loader)
	{
		MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
		MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());

		mVertexFormat = VertexColourType::ColourABGR;

		mUpdate = false;
		mImageLoader = _loader;

		glewInit();

		mPboIsSupported = glewIsExtensionSupported("GL_EXT_pixel_buffer_object") != 0;

		MYGUI_LOG(Info, getClassTypeName() << " successfully initialized");
		mIsInitialise = true;
	}

	void OpenGLRenderManager::shutdown()
	{
		MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
		MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName());

		destroyAllResources();

		MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown");
		mIsInitialise = false;
	}

	IVertexBuffer* OpenGLRenderManager::createVertexBuffer()
	{
		return new OpenGLVertexBuffer();
	}

	void OpenGLRenderManager::destroyVertexBuffer(IVertexBuffer* _buffer)
	{
		delete _buffer;
	}

	void OpenGLRenderManager::doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count)
	{
		OpenGLVertexBuffer* buffer = static_cast<OpenGLVertexBuffer*>(_buffer);
		unsigned int buffer_id = buffer->getBufferID();
		MYGUI_PLATFORM_ASSERT(buffer_id, "Vertex buffer is not created");

		unsigned int texture_id = 0;
		if (_texture)
		{
			OpenGLTexture* texture = static_cast<OpenGLTexture*>(_texture);
			texture_id = texture->getTextureID();
			//MYGUI_PLATFORM_ASSERT(texture_id, "Texture is not created");
		}

		glBindTexture(GL_TEXTURE_2D, texture_id);

		glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer_id);

		// enable vertex arrays
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		// before draw, specify vertex and index arrays with their offsets
		size_t offset = 0;
		glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offset);
		offset += (sizeof(float) * 3);
		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (void*)offset);
		offset += (4);
		glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offset);

		glDrawArrays(GL_TRIANGLES, 0, _count);

		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);

		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	void OpenGLRenderManager::begin()
	{
		//save current attributes
		glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
		glPushAttrib(GL_ALL_ATTRIB_BITS);

		glPolygonMode(GL_FRONT, GL_FILL);
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		glOrtho(-1, 1, -1, 1, -1, 1);

		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();

		glDisable(GL_LIGHTING);
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_FOG);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		glDisable(GL_TEXTURE_GEN_R);

		//glFrontFace(GL_CW);
		//glCullFace(GL_BACK);
		//glEnable(GL_CULL_FACE);

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		glEnable(GL_TEXTURE_2D);
	}

	void OpenGLRenderManager::end()
	{
		glPopMatrix();
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);

		//restore former attributes
		glPopAttrib();
		glPopClientAttrib();
	}

	const RenderTargetInfo& OpenGLRenderManager::getInfo()
	{
		return mInfo;
	}

	const IntSize& OpenGLRenderManager::getViewSize() const
	{
		return mViewSize;
	}

	VertexColourType OpenGLRenderManager::getVertexFormat()
	{
		return mVertexFormat;
	}

	void OpenGLRenderManager::drawOneFrame()
	{
		Gui* gui = Gui::getInstancePtr();
		if (gui == nullptr)
			return;

		static Timer timer;
		static unsigned long last_time = timer.getMilliseconds();
		unsigned long now_time = timer.getMilliseconds();
		unsigned long time = now_time - last_time;

		gui->_injectFrameEntered((float)((double)(time) / (double)1000));

		last_time = now_time;

		begin();
		LayerManager::getInstance().renderToTarget(this, mUpdate);
		end();

		mUpdate = false;
	}

	void OpenGLRenderManager::setViewSize(int _width, int _height)
	{
		if (_height == 0)
			_height = 1;
		if (_width == 0)
			_width = 1;

		mViewSize.set(_width, _height);

		mInfo.maximumDepth = 1;
		mInfo.hOffset = 0;
		mInfo.vOffset = 0;
		mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width);
		mInfo.pixScaleX = 1.0f / float(mViewSize.width);
		mInfo.pixScaleY = 1.0f / float(mViewSize.height);

		Gui* gui = Gui::getInstancePtr();
		if (gui != nullptr)
		{
			gui->_resizeWindow(mViewSize);
			mUpdate = true;
		}
	}

	bool OpenGLRenderManager::isPixelBufferObjectSupported()
	{
		return mPboIsSupported;
	}

	ITexture* OpenGLRenderManager::createTexture(const std::string& _name)
	{
		MapTexture::const_iterator item = mTextures.find(_name);
		MYGUI_PLATFORM_ASSERT(item == mTextures.end(), "Texture '" << _name << "' already exist");

		OpenGLTexture* texture = new OpenGLTexture(_name, mImageLoader);
		mTextures[_name] = texture;
		return texture;
	}

	void OpenGLRenderManager::destroyTexture(ITexture* _texture)
	{
		if (_texture == nullptr) return;

		MapTexture::iterator item = mTextures.find(_texture->getName());
		MYGUI_PLATFORM_ASSERT(item != mTextures.end(), "Texture '" << _texture->getName() << "' not found");

		mTextures.erase(item);
		delete _texture;
	}

	ITexture* OpenGLRenderManager::getTexture(const std::string& _name)
	{
		MapTexture::const_iterator item = mTextures.find(_name);
		if (item == mTextures.end()) return nullptr;
		return item->second;
	}

	void OpenGLRenderManager::destroyAllResources()
	{
		for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item)
		{
			delete item->second;
		}
		mTextures.clear();
	}

} // namespace MyGUI
<commit_msg>refactoring OpenGL platform<commit_after>/*!
	@file
	@author		George Evmenov
	@date		07/2009
*/

#include "MyGUI_OpenGLRenderManager.h"
#include "MyGUI_OpenGLTexture.h"
#include "MyGUI_OpenGLVertexBuffer.h"
#include "MyGUI_OpenGLDiagnostic.h"
#include "MyGUI_VertexData.h"
#include "MyGUI_Gui.h"
#include "MyGUI_Timer.h"

#include "GL/glew.h"

namespace MyGUI
{

	OpenGLRenderManager::OpenGLRenderManager() :
		mUpdate(false),
		mImageLoader(nullptr),
		mPboIsSupported(false),
		mIsInitialise(false)
	{
	}

	void OpenGLRenderManager::initialise(OpenGLImageLoader* _loader)
	{
		MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
		MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());

		mVertexFormat = VertexColourType::ColourABGR;

		mUpdate = false;
		mImageLoader = _loader;

		glewInit();

		mPboIsSupported = glewIsExtensionSupported("GL_EXT_pixel_buffer_object") != 0;

		MYGUI_LOG(Info, getClassTypeName() << " successfully initialized");
		mIsInitialise = true;
	}

	void OpenGLRenderManager::shutdown()
	{
		MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
		MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName());

		destroyAllResources();

		MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown");
		mIsInitialise = false;
	}

	IVertexBuffer* OpenGLRenderManager::createVertexBuffer()
	{
		return new OpenGLVertexBuffer();
	}

	void OpenGLRenderManager::destroyVertexBuffer(IVertexBuffer* _buffer)
	{
		delete _buffer;
	}

	void OpenGLRenderManager::doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count)
	{
		OpenGLVertexBuffer* buffer = static_cast<OpenGLVertexBuffer*>(_buffer);
		unsigned int buffer_id = buffer->getBufferID();
		MYGUI_PLATFORM_ASSERT(buffer_id, "Vertex buffer is not created");

		unsigned int texture_id = 0;
		if (_texture)
		{
			OpenGLTexture* texture = static_cast<OpenGLTexture*>(_texture);
			texture_id = texture->getTextureID();
			//MYGUI_PLATFORM_ASSERT(texture_id, "Texture is not created");
		}

		glBindTexture(GL_TEXTURE_2D, texture_id);

		glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer_id);

		// enable vertex arrays
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		// before draw, specify vertex and index arrays with their offsets
		size_t offset = 0;
		glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offset);
		offset += (sizeof(float) * 3);
		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (void*)offset);
		offset += (4);
		glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offset);

		glDrawArrays(GL_TRIANGLES, 0, _count);

		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);

		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	void OpenGLRenderManager::begin()
	{
		//save current attributes
		glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
		glPushAttrib(GL_ALL_ATTRIB_BITS);

		glPolygonMode(GL_FRONT, GL_FILL);
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		glOrtho(-1, 1, -1, 1, -1, 1);

		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();

		glDisable(GL_LIGHTING);
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_FOG);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		glDisable(GL_TEXTURE_GEN_R);

		//glFrontFace(GL_CW);
		//glCullFace(GL_BACK);
		//glEnable(GL_CULL_FACE);

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		glEnable(GL_TEXTURE_2D);
	}

	void OpenGLRenderManager::end()
	{
		glPopMatrix();
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);

		//restore former attributes
		glPopAttrib();
		glPopClientAttrib();
	}

	const RenderTargetInfo& OpenGLRenderManager::getInfo()
	{
		return mInfo;
	}

	const IntSize& OpenGLRenderManager::getViewSize() const
	{
		return mViewSize;
	}

	VertexColourType OpenGLRenderManager::getVertexFormat()
	{
		return mVertexFormat;
	}

	void OpenGLRenderManager::drawOneFrame()
	{
		Gui* gui = Gui::getInstancePtr();
		if (gui == nullptr)
			return;

		static Timer timer;
		static unsigned long last_time = timer.getMilliseconds();
		unsigned long now_time = timer.getMilliseconds();
		unsigned long time = now_time - last_time;

		onFrameEvent((float)((double)(time) / (double)1000));

		last_time = now_time;

		begin();
		onRenderToTarget(this, mUpdate);
		end();

		mUpdate = false;
	}

	void OpenGLRenderManager::setViewSize(int _width, int _height)
	{
		if (_height == 0)
			_height = 1;
		if (_width == 0)
			_width = 1;

		mViewSize.set(_width, _height);

		mInfo.maximumDepth = 1;
		mInfo.hOffset = 0;
		mInfo.vOffset = 0;
		mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width);
		mInfo.pixScaleX = 1.0f / float(mViewSize.width);
		mInfo.pixScaleY = 1.0f / float(mViewSize.height);

		onResizeView(mViewSize);
		mUpdate = true;
	}

	bool OpenGLRenderManager::isPixelBufferObjectSupported()
	{
		return mPboIsSupported;
	}

	ITexture* OpenGLRenderManager::createTexture(const std::string& _name)
	{
		MapTexture::const_iterator item = mTextures.find(_name);
		MYGUI_PLATFORM_ASSERT(item == mTextures.end(), "Texture '" << _name << "' already exist");

		OpenGLTexture* texture = new OpenGLTexture(_name, mImageLoader);
		mTextures[_name] = texture;
		return texture;
	}

	void OpenGLRenderManager::destroyTexture(ITexture* _texture)
	{
		if (_texture == nullptr)
			return;

		MapTexture::iterator item = mTextures.find(_texture->getName());
		MYGUI_PLATFORM_ASSERT(item != mTextures.end(), "Texture '" << _texture->getName() << "' not found");

		mTextures.erase(item);
		delete _texture;
	}

	ITexture* OpenGLRenderManager::getTexture(const std::string& _name)
	{
		MapTexture::const_iterator item = mTextures.find(_name);
		if (item == mTextures.end())
			return nullptr;
		return item->second;
	}

	void OpenGLRenderManager::destroyAllResources()
	{
		for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item)
		{
			delete item->second;
		}
		mTextures.clear();
	}

} // namespace MyGUI
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include <affine_invariant_features/affine_invariant_feature.hpp>
#include <affine_invariant_features/feature_parameters.hpp>
#include <affine_invariant_features/results.hpp>
#include <affine_invariant_features/target.hpp>

#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/highgui.hpp>

int main(int argc, char *argv[]) {
  namespace aif = affine_invariant_features;

  if (argc != 4) {
    std::cout << "Usage: extract_features <parameter_file> <target_file> <result_file>"
              << std::endl;
    std::cout << "Note: use generate_*_file to generate parameter or target files" << std::endl;
    return 0;
  }

  const std::string param_path(argv[1]);
  const std::string target_path(argv[2]);
  const std::string result_path(argv[3]);

  const cv::FileStorage param_file(param_path, cv::FileStorage::READ);
  const cv::Ptr< const aif::FeatureParameters > params(
      aif::readFeatureParameters(param_file.root()));
  if (!params) {
    std::cerr << "Could not load a parameter set from " << param_path << std::endl;
    return 1;
  }

  const cv::FileStorage target_file(target_path, cv::FileStorage::READ);
  aif::TargetDescription target_desc;
  target_file[target_desc.getDefaultName()] >> target_desc;
  if (target_desc.imagePath.empty()) {
    std::cerr << "Could not load an image path from " << target_path << std::endl;
    return 1;
  }

  const aif::TargetData target_data(target_desc.toData());
  if (target_data.image.empty()) {
    std::cerr << "Could not load a target image described in " << target_path << std::endl;
    return 1;
  }

  cv::Mat target_image;
  if (target_data.mask.empty()) {
    target_image = target_data.image.clone();
  } else {
    target_image = target_data.image / 4;
    target_data.image.copyTo(target_image, target_data.mask);
  }
  std::cout << "Showing the target image with mask. Press any key to continue." << std::endl;
  cv::imshow("Target", target_image);
  cv::waitKey(0);

  std::cout << "Extracting features. This may take seconds or minutes." << std::endl;
  const cv::Ptr< cv::Feature2D > feature(
      aif::AffineInvariantFeature::create(params->createFeature()));
  aif::Results results;
  feature->detectAndCompute(target_data.image, target_data.mask, results.keypoints,
                            results.descriptors);
  results.normType = feature->defaultNorm();

  cv::Mat result_image;
  cv::drawKeypoints(target_image, results.keypoints, result_image);
  std::cout << "Showing a result image with keypoints. Press any key to continue." << std::endl;
  cv::imshow("Resutls", result_image);
  cv::waitKey(0);

  cv::FileStorage result_file(result_path, cv::FileStorage::WRITE);
  result_file << params->getDefaultName() << *params;
  result_file << target_desc.getDefaultName() << target_desc;
  result_file << results.getDefaultName() << results;

  std::cout << "Wrote context and results of feature extraction to " << result_path << std::endl;

  return 0;
}
<commit_msg>refactor extract_features<commit_after>#include <iostream>
#include <string>

#include <affine_invariant_features/affine_invariant_feature.hpp>
#include <affine_invariant_features/feature_parameters.hpp>
#include <affine_invariant_features/results.hpp>
#include <affine_invariant_features/target.hpp>

#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/highgui.hpp>

int main(int argc, char *argv[]) {
  namespace aif = affine_invariant_features;

  const cv::CommandLineParser args(
      argc, argv, "{ help | | }"
                  "{ use-simple-feature | <none> | will not use affine invariant sampling }"
                  "{ @parameter-file | <none> | can be generated by generate_parameter_file }"
                  "{ @target-file | <none> | can be generated by generate_target_file }"
                  "{ @result-file | <none> | }");

  if (args.has("help")) {
    args.printMessage();
    return 0;
  }

  const bool use_simple_feature(args.has("use-simple-feature"));
  const std::string param_path(args.get< std::string >("@parameter-file"));
  const std::string target_path(args.get< std::string >("@target-file"));
  const std::string result_path(args.get< std::string >("@result-file"));
  if (!args.check()) {
    args.printErrors();
    return 1;
  }

  const cv::FileStorage param_file(param_path, cv::FileStorage::READ);
  if (!param_file.isOpened()) {
    std::cerr << "Could not open " << param_path << std::endl;
    return 1;
  }

  const cv::Ptr< const aif::FeatureParameters > params(
      aif::readFeatureParameters(param_file.root()));
  if (!params) {
    std::cerr << "Could not load a parameter set from " << param_path << std::endl;
    return 1;
  }

  const cv::FileStorage target_file(target_path, cv::FileStorage::READ);
  if (!target_file.isOpened()) {
    std::cerr << "Could not open " << target_path << std::endl;
    return 1;
  }

  aif::TargetDescription target_desc;
  target_file[target_desc.getDefaultName()] >> target_desc;
  if (target_desc.imagePath.empty()) {
    std::cerr << "Could not load an image path from " << target_path << std::endl;
    return 1;
  }

  const aif::TargetData target_data(target_desc.toData());
  if (target_data.image.empty()) {
    std::cerr << "Could not load a target image described in " << target_path << std::endl;
    return 1;
  }

  cv::Mat target_image;
  if (target_data.mask.empty()) {
    target_image = target_data.image.clone();
  } else {
    target_image = target_data.image / 4;
    target_data.image.copyTo(target_image, target_data.mask);
  }
  std::cout << "Showing the target image with mask. Press any key to continue." << std::endl;
  cv::imshow("Target", target_image);
  cv::waitKey(0);

  std::cout << "Extracting features. This may take seconds or minutes." << std::endl;
  cv::Ptr< cv::Feature2D > feature;
  if (use_simple_feature) {
    feature = params->createFeature();
  } else {
    feature = aif::AffineInvariantFeature::create(params->createFeature());
  }
  aif::Results results;
  feature->detectAndCompute(target_data.image, target_data.mask, results.keypoints,
                            results.descriptors);
  results.normType = feature->defaultNorm();

  cv::Mat result_image;
  cv::drawKeypoints(target_image, results.keypoints, result_image);
  std::cout << "Showing a result image with keypoints. Press any key to continue." << std::endl;
  cv::imshow("Resutls", result_image);
  cv::waitKey(0);

  cv::FileStorage result_file(result_path, cv::FileStorage::WRITE);
  if(!result_file.isOpened()){
    std::cerr << "Could not open or create " << result_path << std::endl;
    return 1;
  }

  result_file << params->getDefaultName() << *params;
  result_file << target_desc.getDefaultName() << target_desc;
  result_file << results.getDefaultName() << results;
  std::cout << "Wrote context and results of feature extraction to " << result_path << std::endl;

  return 0;
}
<|endoftext|>