<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPath.h"
#include "SkRect.h"
#include "SkRemote.h"

namespace SkRemote {

    Misc Misc::CreateFrom(const SkPaint& paint) {
        Misc misc = {
            paint.getColor(),
            paint.getFilterQuality(),
            paint.isAntiAlias(),
            paint.isDither(),
        };
        return misc;
    }

    void Misc::applyTo(SkPaint* paint) const {
        paint->setColor        (fColor);
        paint->setFilterQuality(fFilterQuality);
        paint->setAntiAlias    (fAntiAlias);
        paint->setDither       (fDither);
    }

    static bool operator==(const Misc& a, const Misc& b) {
        return a.fColor         == b.fColor
            && a.fFilterQuality == b.fFilterQuality
            && a.fAntiAlias     == b.fAntiAlias
            && a.fDither        == b.fDither;
    }

    Stroke Stroke::CreateFrom(const SkPaint& paint) {
        Stroke stroke = {
            paint.getStrokeWidth(),
            paint.getStrokeMiter(),
            paint.getStrokeCap(),
            paint.getStrokeJoin(),
        };
        return stroke;
    }

    void Stroke::applyTo(SkPaint* paint) const {
        paint->setStrokeWidth(fWidth);
        paint->setStrokeMiter(fMiter);
        paint->setStrokeCap  (fCap);
        paint->setStrokeJoin (fJoin);
    }

    static bool operator==(const Stroke& a, const Stroke& b) {
        return a.fWidth == b.fWidth
            && a.fMiter == b.fMiter
            && a.fCap   == b.fCap
            && a.fJoin  == b.fJoin;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

    class LookupScope {
    public:
        LookupScope(Cache* cache, Encoder* encoder) : fCache(cache), fEncoder(encoder) {}
        ~LookupScope() { for (ID id : fToUndefine) { fEncoder->undefine(id); } }
        void undefineWhenDone(ID id) { fToUndefine.push_back(id); }

        template <typename T>
        ID lookup(const T& val) {
            ID id;
            if (!fCache->lookup(val, &id, this)) {
                fEncoder->define(id, val);
            }
            return id;
        }

    private:
        Cache*   fCache;
        Encoder* fEncoder;
        SkSTArray<4, ID> fToUndefine;
    };

    Cache* Cache::CreateNeverCache() {
        struct NeverCache final : public Cache {
            NeverCache()
                : fNextMatrix(Type::kMatrix)
                , fNextMisc  (Type::kMisc)
                , fNextPath  (Type::kPath)
                , fNextStroke(Type::kStroke)
            {}
            void cleanup(Encoder*) override {}

            static bool Helper(ID* next, ID* id, LookupScope* ls) {
                *id = (*next)++;
                ls->undefineWhenDone(*id);
                return false;
            }

            bool lookup(const SkMatrix&, ID* id, LookupScope* ls) override {
                return Helper(&fNextMatrix, id, ls);
            }
            bool lookup(const Misc&, ID* id, LookupScope* ls) override {
                return Helper(&fNextMisc, id, ls);
            }
            bool lookup(const SkPath&, ID* id, LookupScope* ls) override {
                return Helper(&fNextPath, id, ls);
            }
            bool lookup(const Stroke&, ID* id, LookupScope* ls) override {
                return Helper(&fNextStroke, id, ls);
            }

            ID fNextMatrix,
               fNextMisc,
               fNextPath,
               fNextStroke;
        };
        return new NeverCache;
    }

    // Can't be declared locally inside AlwaysCache because of the templating.  :(
    template <typename T, typename Map>
    static bool always_cache_helper(const T& val, Map* map, ID* next, ID* id) {
        if (ID* found = map->find(val)) {
            *id = *found;
            return true;
        }
        *id = (*next)++;
        map->set(val, *id);
        return false;
    }

    Cache* Cache::CreateAlwaysCache() {
        struct AlwaysCache final : public Cache {
            AlwaysCache()
                : fNextMatrix(Type::kMatrix)
                , fNextMisc  (Type::kMisc)
                , fNextPath  (Type::kPath)
                , fNextStroke(Type::kStroke)
            {}

            void cleanup(Encoder* encoder) override {
                fMatrix.foreach([=](const SkMatrix&, ID* id) { encoder->undefine(*id); });
                fMisc  .foreach([=](const Misc&,     ID* id) { encoder->undefine(*id); });
                fPath  .foreach([=](const SkPath&,   ID* id) { encoder->undefine(*id); });
                fStroke.foreach([=](const Stroke&,   ID* id) { encoder->undefine(*id); });
            }

            bool lookup(const SkMatrix& matrix, ID* id, LookupScope*) override {
                return always_cache_helper(matrix, &fMatrix, &fNextMatrix, id);
            }
            bool lookup(const Misc& misc, ID* id, LookupScope*) override {
                return always_cache_helper(misc, &fMisc, &fNextMisc, id);
            }
            bool lookup(const SkPath& path, ID* id, LookupScope*) override {
                return always_cache_helper(path, &fPath, &fNextPath, id);
            }
            bool lookup(const Stroke& stroke, ID* id, LookupScope*) override {
                return always_cache_helper(stroke, &fStroke, &fNextStroke, id);
            }

            SkTHashMap<SkMatrix, ID> fMatrix;
            SkTHashMap<Misc,     ID> fMisc;
            SkTHashMap<SkPath,   ID> fPath;
            SkTHashMap<Stroke,   ID> fStroke;
            ID fNextMatrix,
               fNextMisc,
               fNextPath,
               fNextStroke;
        };
        return new AlwaysCache;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

    Client::Client(Cache* cache, Encoder* encoder)
        : SkCanvas(1,1)
        , fCache(cache)
        , fEncoder(encoder)
    {}

    Client::~Client() {
        fCache->cleanup(fEncoder);
    }

    void Client::willSave()   { fEncoder->save(); }
    void Client::didRestore() { fEncoder->restore(); }

    void Client::didConcat   (const SkMatrix&) { this->didSetMatrix(this->getTotalMatrix()); }
    void Client::didSetMatrix(const SkMatrix& matrix) {
        LookupScope ls(fCache, fEncoder);
        fEncoder->setMatrix(ls.lookup(matrix));
    }

    void Client::onDrawOval(const SkRect& oval, const SkPaint& paint) {
        SkPath path;
        path.addOval(oval);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawRect(const SkRect& rect, const SkPaint& paint) {
        SkPath path;
        path.addRect(rect);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
        SkPath path;
        path.addRRect(rrect);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawDRRect(const SkRRect& outside,
                              const SkRRect& inside,
                              const SkPaint& paint) {
        SkPath path;
        path.addRRect(outside);
        path.addRRect(inside, SkPath::kCCW_Direction);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawPath(const SkPath& path, const SkPaint& paint) {
        LookupScope ls(fCache, fEncoder);
        ID p = ls.lookup(path),
           m = ls.lookup(Misc::CreateFrom(paint));

        if (paint.getStyle() == SkPaint::kFill_Style) {
            fEncoder->fillPath(p, m);
        } else {
            // TODO: handle kStrokeAndFill_Style
            fEncoder->strokePath(p, m, ls.lookup(Stroke::CreateFrom(paint)));
        }
    }

    void Client::onDrawPaint(const SkPaint& paint) {
        this->onDrawRect(SkRect::MakeLargest(), paint);
    }

    void Client::onDrawText(const void* text, size_t byteLength, SkScalar x,
                            SkScalar y, const SkPaint& paint) {
        // Text-as-paths is a temporary hack.
        // TODO: send SkTextBlobs and SkTypefaces
        SkPath path;
        paint.getTextPath(text, byteLength, x, y, &path);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawPosText(const void* text, size_t byteLength,
                               const SkPoint pos[], const SkPaint& paint) {
        // Text-as-paths is a temporary hack.
        // TODO: send SkTextBlobs and SkTypefaces
        SkPath path;
        paint.getPosTextPath(text, byteLength, pos, &path);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawPosTextH(const void* text, size_t byteLength,
                                const SkScalar xpos[], SkScalar constY,
                                const SkPaint& paint) {
        size_t length = paint.countText(text, byteLength);
        SkAutoTArray<SkPoint> pos(length);
        for(size_t i = 0; i < length; ++i) {
            pos[i].set(xpos[i], constY);
        }
        this->onDrawPosText(text, byteLength, &pos[0], paint);
    }

    void Client::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
        SkPath path;
        path.addRect(rect);
        this->onClipPath(path, op, edgeStyle);
    }

    void Client::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
        SkPath path;
        path.addRRect(rrect);
        this->onClipPath(path, op, edgeStyle);
    }

    void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
        LookupScope ls(fCache, fEncoder);
        fEncoder->clipPath(ls.lookup(path), op, edgeStyle == kSoft_ClipEdgeStyle);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

    Server::Server(SkCanvas* canvas) : fCanvas(canvas) {}

    void Server::define(ID id, const SkMatrix& v) { fMatrix.set(id, v); }
    void Server::define(ID id, const Misc&     v) { fMisc  .set(id, v); }
    void Server::define(ID id, const SkPath&   v) { fPath  .set(id, v); }
    void Server::define(ID id, const Stroke&   v) { fStroke.set(id, v); }

    void Server::undefine(ID id) {
        switch(id.type()) {
            case Type::kMatrix: return fMatrix.remove(id);
            case Type::kMisc:   return fMisc  .remove(id);
            case Type::kPath:   return fPath  .remove(id);
            case Type::kStroke: return fStroke.remove(id);

            case Type::kNone: SkASSERT(false);
        };
    }

    void Server::   save() { fCanvas->save(); }
    void Server::restore() { fCanvas->restore(); }

    void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix)); }

    void Server::clipPath(ID path, SkRegion::Op op, bool aa) {
        fCanvas->clipPath(fPath.find(path), op, aa);
    }
    void Server::fillPath(ID path, ID misc) {
        SkPaint paint;
        paint.setStyle(SkPaint::kFill_Style);
        fMisc.find(misc).applyTo(&paint);
        fCanvas->drawPath(fPath.find(path), paint);
    }
    void Server::strokePath(ID path, ID misc, ID stroke) {
        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);
        fMisc  .find(misc  ).applyTo(&paint);
        fStroke.find(stroke).applyTo(&paint);
        fCanvas->drawPath(fPath.find(path), paint);
    }

} // namespace SkRemote
<commit_msg>SkRemote: DrawPaint is an inverse empty path.<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPath.h"
#include "SkRect.h"
#include "SkRemote.h"

namespace SkRemote {

    Misc Misc::CreateFrom(const SkPaint& paint) {
        Misc misc = {
            paint.getColor(),
            paint.getFilterQuality(),
            paint.isAntiAlias(),
            paint.isDither(),
        };
        return misc;
    }

    void Misc::applyTo(SkPaint* paint) const {
        paint->setColor        (fColor);
        paint->setFilterQuality(fFilterQuality);
        paint->setAntiAlias    (fAntiAlias);
        paint->setDither       (fDither);
    }

    static bool operator==(const Misc& a, const Misc& b) {
        return a.fColor         == b.fColor
            && a.fFilterQuality == b.fFilterQuality
            && a.fAntiAlias     == b.fAntiAlias
            && a.fDither        == b.fDither;
    }

    Stroke Stroke::CreateFrom(const SkPaint& paint) {
        Stroke stroke = {
            paint.getStrokeWidth(),
            paint.getStrokeMiter(),
            paint.getStrokeCap(),
            paint.getStrokeJoin(),
        };
        return stroke;
    }

    void Stroke::applyTo(SkPaint* paint) const {
        paint->setStrokeWidth(fWidth);
        paint->setStrokeMiter(fMiter);
        paint->setStrokeCap  (fCap);
        paint->setStrokeJoin (fJoin);
    }

    static bool operator==(const Stroke& a, const Stroke& b) {
        return a.fWidth == b.fWidth
            && a.fMiter == b.fMiter
            && a.fCap   == b.fCap
            && a.fJoin  == b.fJoin;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

    class LookupScope {
    public:
        LookupScope(Cache* cache, Encoder* encoder) : fCache(cache), fEncoder(encoder) {}
        ~LookupScope() { for (ID id : fToUndefine) { fEncoder->undefine(id); } }
        void undefineWhenDone(ID id) { fToUndefine.push_back(id); }

        template <typename T>
        ID lookup(const T& val) {
            ID id;
            if (!fCache->lookup(val, &id, this)) {
                fEncoder->define(id, val);
            }
            return id;
        }

    private:
        Cache*   fCache;
        Encoder* fEncoder;
        SkSTArray<4, ID> fToUndefine;
    };

    Cache* Cache::CreateNeverCache() {
        struct NeverCache final : public Cache {
            NeverCache()
                : fNextMatrix(Type::kMatrix)
                , fNextMisc  (Type::kMisc)
                , fNextPath  (Type::kPath)
                , fNextStroke(Type::kStroke)
            {}
            void cleanup(Encoder*) override {}

            static bool Helper(ID* next, ID* id, LookupScope* ls) {
                *id = (*next)++;
                ls->undefineWhenDone(*id);
                return false;
            }

            bool lookup(const SkMatrix&, ID* id, LookupScope* ls) override {
                return Helper(&fNextMatrix, id, ls);
            }
            bool lookup(const Misc&, ID* id, LookupScope* ls) override {
                return Helper(&fNextMisc, id, ls);
            }
            bool lookup(const SkPath&, ID* id, LookupScope* ls) override {
                return Helper(&fNextPath, id, ls);
            }
            bool lookup(const Stroke&, ID* id, LookupScope* ls) override {
                return Helper(&fNextStroke, id, ls);
            }

            ID fNextMatrix,
               fNextMisc,
               fNextPath,
               fNextStroke;
        };
        return new NeverCache;
    }

    // Can't be declared locally inside AlwaysCache because of the templating.  :(
    template <typename T, typename Map>
    static bool always_cache_helper(const T& val, Map* map, ID* next, ID* id) {
        if (ID* found = map->find(val)) {
            *id = *found;
            return true;
        }
        *id = (*next)++;
        map->set(val, *id);
        return false;
    }

    Cache* Cache::CreateAlwaysCache() {
        struct AlwaysCache final : public Cache {
            AlwaysCache()
                : fNextMatrix(Type::kMatrix)
                , fNextMisc  (Type::kMisc)
                , fNextPath  (Type::kPath)
                , fNextStroke(Type::kStroke)
            {}

            void cleanup(Encoder* encoder) override {
                fMatrix.foreach([=](const SkMatrix&, ID* id) { encoder->undefine(*id); });
                fMisc  .foreach([=](const Misc&,     ID* id) { encoder->undefine(*id); });
                fPath  .foreach([=](const SkPath&,   ID* id) { encoder->undefine(*id); });
                fStroke.foreach([=](const Stroke&,   ID* id) { encoder->undefine(*id); });
            }

            bool lookup(const SkMatrix& matrix, ID* id, LookupScope*) override {
                return always_cache_helper(matrix, &fMatrix, &fNextMatrix, id);
            }
            bool lookup(const Misc& misc, ID* id, LookupScope*) override {
                return always_cache_helper(misc, &fMisc, &fNextMisc, id);
            }
            bool lookup(const SkPath& path, ID* id, LookupScope*) override {
                return always_cache_helper(path, &fPath, &fNextPath, id);
            }
            bool lookup(const Stroke& stroke, ID* id, LookupScope*) override {
                return always_cache_helper(stroke, &fStroke, &fNextStroke, id);
            }

            SkTHashMap<SkMatrix, ID> fMatrix;
            SkTHashMap<Misc,     ID> fMisc;
            SkTHashMap<SkPath,   ID> fPath;
            SkTHashMap<Stroke,   ID> fStroke;
            ID fNextMatrix,
               fNextMisc,
               fNextPath,
               fNextStroke;
        };
        return new AlwaysCache;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

    Client::Client(Cache* cache, Encoder* encoder)
        : SkCanvas(1,1)
        , fCache(cache)
        , fEncoder(encoder)
    {}

    Client::~Client() {
        fCache->cleanup(fEncoder);
    }

    void Client::willSave()   { fEncoder->save(); }
    void Client::didRestore() { fEncoder->restore(); }

    void Client::didConcat   (const SkMatrix&) { this->didSetMatrix(this->getTotalMatrix()); }
    void Client::didSetMatrix(const SkMatrix& matrix) {
        LookupScope ls(fCache, fEncoder);
        fEncoder->setMatrix(ls.lookup(matrix));
    }

    void Client::onDrawOval(const SkRect& oval, const SkPaint& paint) {
        SkPath path;
        path.addOval(oval);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawRect(const SkRect& rect, const SkPaint& paint) {
        SkPath path;
        path.addRect(rect);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
        SkPath path;
        path.addRRect(rrect);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawDRRect(const SkRRect& outside,
                              const SkRRect& inside,
                              const SkPaint& paint) {
        SkPath path;
        path.addRRect(outside);
        path.addRRect(inside, SkPath::kCCW_Direction);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawPath(const SkPath& path, const SkPaint& paint) {
        LookupScope ls(fCache, fEncoder);
        ID p = ls.lookup(path),
           m = ls.lookup(Misc::CreateFrom(paint));

        if (paint.getStyle() == SkPaint::kFill_Style) {
            fEncoder->fillPath(p, m);
        } else {
            // TODO: handle kStrokeAndFill_Style
            fEncoder->strokePath(p, m, ls.lookup(Stroke::CreateFrom(paint)));
        }
    }

    void Client::onDrawPaint(const SkPaint& paint) {
        SkPath path;
        path.setFillType(SkPath::kInverseWinding_FillType);  // Either inverse FillType works fine.
        this->onDrawPath(path, paint);
    }

    void Client::onDrawText(const void* text, size_t byteLength, SkScalar x,
                            SkScalar y, const SkPaint& paint) {
        // Text-as-paths is a temporary hack.
        // TODO: send SkTextBlobs and SkTypefaces
        SkPath path;
        paint.getTextPath(text, byteLength, x, y, &path);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawPosText(const void* text, size_t byteLength,
                               const SkPoint pos[], const SkPaint& paint) {
        // Text-as-paths is a temporary hack.
        // TODO: send SkTextBlobs and SkTypefaces
        SkPath path;
        paint.getPosTextPath(text, byteLength, pos, &path);
        this->onDrawPath(path, paint);
    }

    void Client::onDrawPosTextH(const void* text, size_t byteLength,
                                const SkScalar xpos[], SkScalar constY,
                                const SkPaint& paint) {
        size_t length = paint.countText(text, byteLength);
        SkAutoTArray<SkPoint> pos(length);
        for(size_t i = 0; i < length; ++i) {
            pos[i].set(xpos[i], constY);
        }
        this->onDrawPosText(text, byteLength, &pos[0], paint);
    }

    void Client::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
        SkPath path;
        path.addRect(rect);
        this->onClipPath(path, op, edgeStyle);
    }

    void Client::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
        SkPath path;
        path.addRRect(rrect);
        this->onClipPath(path, op, edgeStyle);
    }

    void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
        LookupScope ls(fCache, fEncoder);
        fEncoder->clipPath(ls.lookup(path), op, edgeStyle == kSoft_ClipEdgeStyle);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

    Server::Server(SkCanvas* canvas) : fCanvas(canvas) {}

    void Server::define(ID id, const SkMatrix& v) { fMatrix.set(id, v); }
    void Server::define(ID id, const Misc&     v) { fMisc  .set(id, v); }
    void Server::define(ID id, const SkPath&   v) { fPath  .set(id, v); }
    void Server::define(ID id, const Stroke&   v) { fStroke.set(id, v); }

    void Server::undefine(ID id) {
        switch(id.type()) {
            case Type::kMatrix: return fMatrix.remove(id);
            case Type::kMisc:   return fMisc  .remove(id);
            case Type::kPath:   return fPath  .remove(id);
            case Type::kStroke: return fStroke.remove(id);

            case Type::kNone: SkASSERT(false);
        };
    }

    void Server::   save() { fCanvas->save(); }
    void Server::restore() { fCanvas->restore(); }

    void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix)); }

    void Server::clipPath(ID path, SkRegion::Op op, bool aa) {
        fCanvas->clipPath(fPath.find(path), op, aa);
    }
    void Server::fillPath(ID path, ID misc) {
        SkPaint paint;
        paint.setStyle(SkPaint::kFill_Style);
        fMisc.find(misc).applyTo(&paint);
        fCanvas->drawPath(fPath.find(path), paint);
    }
    void Server::strokePath(ID path, ID misc, ID stroke) {
        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);
        fMisc  .find(misc  ).applyTo(&paint);
        fStroke.find(stroke).applyTo(&paint);
        fCanvas->drawPath(fPath.find(path), paint);
    }

} // namespace SkRemote
<|endoftext|>


<commit_before><commit_msg>fix for translation to cudaDataType<commit_after><|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include <stdafx.h>

#include <core/support/Common.h>
#include <cursespp/Text.h>
#include <cursespp/ScrollAdapterBase.h>
#include <cursespp/SingleLineEntry.h>

#include "DirectoryAdapter.h"

using namespace musik::cube;
using namespace cursespp;
using namespace boost::filesystem;

#ifdef WIN32
static void buildDriveList(std::vector<std::string>& target) {
    target.clear();
    static char buffer[4096];
    DWORD result = ::GetLogicalDriveStringsA(4096, buffer);
    if (result) {
        char* current = buffer;
        while (*current) {
            target.push_back(std::string(current));
            current += strlen(current) + 1;
        }
    }
}
#endif

static bool hasSubdirectories(
    boost::filesystem::path p, bool showDotfiles)
{
    try {
        directory_iterator end;
        directory_iterator file(p);

        while (file != end) {
            if (is_directory(file->status())) {
                if (showDotfiles || file->path().leaf().string()[0] != '.') {
                    return true;
                }
            }
            ++file;
        }
    }
    catch (...) {
    }

    return false;
}

static void buildDirectoryList(
    const path& p,
    std::vector<std::string>& target,
    bool showDotfiles)
{
    target.clear();

    try {
        directory_iterator end;
        directory_iterator file(p);

        while (file != end) {
            if (is_directory(file->status())) {
                std::string leaf = file->path().leaf().string();
                if (showDotfiles || leaf[0] != '.') {
                    target.push_back(leaf);
                }
            }
            ++file;
        }
    }
    catch (...) {
    }

    std::sort(
        target.begin(),
        target.end(),
        std::locale(setlocale(LC_ALL, nullptr)));
}

static std::string normalizePath(boost::filesystem::path path) {
    return musik::core::NormalizeDir(path.string());
}

DirectoryAdapter::DirectoryAdapter() {
    this->showDotfiles = false;
    this->dir = musik::core::GetHomeDirectory();
    buildDirectoryList(dir, subdirs, showDotfiles);
}

DirectoryAdapter::~DirectoryAdapter() {

}

void DirectoryAdapter::SetAllowEscapeRoot(bool allow) {
    this->allowEscapeRoot = allow;
}

size_t DirectoryAdapter::Select(cursespp::ListWindow* window) {
    bool hasParent = this->ShowParentPath();
    size_t selectedIndex = NO_INDEX;
    size_t initialIndex = window->GetSelectedIndex();

    if (hasParent && initialIndex == 0) {
        if (selectedIndexStack.size()) {
            selectedIndex = this->selectedIndexStack.top();
            this->selectedIndexStack.pop();
        }

        this->dir = this->dir.parent_path();
    }
    else {
        selectedIndexStack.push(initialIndex);
        this->dir /= this->subdirs[hasParent ? initialIndex - 1 : initialIndex];
    }

#ifdef WIN32
    std::string pathstr = this->dir.string();
    if ((pathstr.size() == 2 && pathstr[1] == ':') ||
        (pathstr.size() == 3 && pathstr[2] == ':'))
    {
        dir = path();
        buildDriveList(subdirs);
        return selectedIndex;
    }
#endif

    buildDirectoryList(dir, subdirs, showDotfiles);
    window->OnAdapterChanged();

    return selectedIndex;
}

void DirectoryAdapter::SetRootDirectory(const std::string& directory) {
    if (directory.size()) {
        dir = rootDir = directory;
    }
    else {
        dir = musik::core::GetHomeDirectory();
        rootDir = boost::filesystem::path();
    }

    buildDirectoryList(dir, subdirs, showDotfiles);
}

std::string DirectoryAdapter::GetFullPathAt(size_t index) {
    bool hasParent = this->ShowParentPath();
    if (hasParent && index == 0) {
        return "";
    }

    index = (hasParent ? index - 1 : index);
    return normalizePath((dir / this->subdirs[index]).string());
}

std::string DirectoryAdapter::GetLeafAt(size_t index) {
    if (this->ShowParentPath() && index == 0) {
        return "..";
    }

    return this->subdirs[index];
}

size_t DirectoryAdapter::IndexOf(const std::string& leaf) {
   for (size_t i = 0; i < this->subdirs.size(); i++) {
        if (this->subdirs[i] == leaf) {
            return i;
        }
    }

   return NO_INDEX;
}

size_t DirectoryAdapter::GetEntryCount() {
    size_t count = subdirs.size();
    return this->ShowParentPath() ? count + 1 : count;
}

void DirectoryAdapter::SetDotfilesVisible(bool visible) {
    if (showDotfiles != visible) {
        showDotfiles = visible;
        buildDirectoryList(dir, subdirs, showDotfiles);
    }
}

std::string DirectoryAdapter::GetParentPath() {
    if (dir.has_parent_path() &&
        normalizePath(this->dir) != normalizePath(this->rootDir))
    {
        return normalizePath(dir.parent_path().string());
    }

    return "";
}

std::string DirectoryAdapter::GetCurrentPath() {
    return normalizePath(dir.string());
}

void DirectoryAdapter::Refresh() {
    buildDirectoryList(dir, subdirs, showDotfiles);
}

bool DirectoryAdapter::ShowParentPath() {
    if (normalizePath(this->dir) == normalizePath(this->rootDir)
        && !this->allowEscapeRoot)
    {
        return false;
    }

    return dir.has_parent_path();
}

bool DirectoryAdapter::HasSubDirectories(size_t index) {
    bool hasParent = this->ShowParentPath();
    if (index == 0 && hasParent) {
        return true;
    }

    index = hasParent ? index - 1 : index;
    return hasSubdirectories(this->dir / this->subdirs[index], this->showDotfiles);
}

bool DirectoryAdapter::HasSubDirectories() {
    return hasSubdirectories(this->dir, this->showDotfiles);
}

IScrollAdapter::EntryPtr DirectoryAdapter::GetEntry(cursespp::ScrollableWindow* window, size_t index) {
    if (this->ShowParentPath()) {
        if (index == 0) {
            return IScrollAdapter::EntryPtr(new SingleLineEntry(".."));
        }
        --index;
    }

    auto text = text::Ellipsize(this->subdirs[index], this->GetWidth());
    return IScrollAdapter::EntryPtr(new SingleLineEntry(text));
}
<commit_msg>Fixed startup crash fix on non-UTF-8 locales.<commit_after>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include <stdafx.h>

#include <core/support/Common.h>
#include <cursespp/Text.h>
#include <cursespp/ScrollAdapterBase.h>
#include <cursespp/SingleLineEntry.h>

#include "DirectoryAdapter.h"

using namespace musik::cube;
using namespace cursespp;
using namespace boost::filesystem;

#ifdef WIN32
static void buildDriveList(std::vector<std::string>& target) {
    target.clear();
    static char buffer[4096];
    DWORD result = ::GetLogicalDriveStringsA(4096, buffer);
    if (result) {
        char* current = buffer;
        while (*current) {
            target.push_back(std::string(current));
            current += strlen(current) + 1;
        }
    }
}
#endif

static bool hasSubdirectories(
    boost::filesystem::path p, bool showDotfiles)
{
    try {
        directory_iterator end;
        directory_iterator file(p);

        while (file != end) {
            if (is_directory(file->status())) {
                if (showDotfiles || file->path().leaf().string()[0] != '.') {
                    return true;
                }
            }
            ++file;
        }
    }
    catch (...) {
    }

    return false;
}

static void buildDirectoryList(
    const path& p,
    std::vector<std::string>& target,
    bool showDotfiles)
{
    target.clear();

    try {
        directory_iterator end;
        directory_iterator file(p);

        while (file != end) {
            if (is_directory(file->status())) {
                std::string leaf = file->path().leaf().string();
                if (showDotfiles || leaf[0] != '.') {
                    target.push_back(leaf);
                }
            }
            ++file;
        }
    }
    catch (...) {
    }

    try {
        std::sort(
            target.begin(),
            target.end(),
            std::locale(setlocale(LC_ALL, nullptr)));
    }
    catch (...) {
        std::sort(target.begin(), target.end());
    }
}

static std::string normalizePath(boost::filesystem::path path) {
    return musik::core::NormalizeDir(path.string());
}

DirectoryAdapter::DirectoryAdapter() {
    this->showDotfiles = false;
    this->dir = musik::core::GetHomeDirectory();
    buildDirectoryList(dir, subdirs, showDotfiles);
}

DirectoryAdapter::~DirectoryAdapter() {

}

void DirectoryAdapter::SetAllowEscapeRoot(bool allow) {
    this->allowEscapeRoot = allow;
}

size_t DirectoryAdapter::Select(cursespp::ListWindow* window) {
    bool hasParent = this->ShowParentPath();
    size_t selectedIndex = NO_INDEX;
    size_t initialIndex = window->GetSelectedIndex();

    if (hasParent && initialIndex == 0) {
        if (selectedIndexStack.size()) {
            selectedIndex = this->selectedIndexStack.top();
            this->selectedIndexStack.pop();
        }

        this->dir = this->dir.parent_path();
    }
    else {
        selectedIndexStack.push(initialIndex);
        this->dir /= this->subdirs[hasParent ? initialIndex - 1 : initialIndex];
    }

#ifdef WIN32
    std::string pathstr = this->dir.string();
    if ((pathstr.size() == 2 && pathstr[1] == ':') ||
        (pathstr.size() == 3 && pathstr[2] == ':'))
    {
        dir = path();
        buildDriveList(subdirs);
        return selectedIndex;
    }
#endif

    buildDirectoryList(dir, subdirs, showDotfiles);
    window->OnAdapterChanged();

    return selectedIndex;
}

void DirectoryAdapter::SetRootDirectory(const std::string& directory) {
    if (directory.size()) {
        dir = rootDir = directory;
    }
    else {
        dir = musik::core::GetHomeDirectory();
        rootDir = boost::filesystem::path();
    }

    buildDirectoryList(dir, subdirs, showDotfiles);
}

std::string DirectoryAdapter::GetFullPathAt(size_t index) {
    bool hasParent = this->ShowParentPath();
    if (hasParent && index == 0) {
        return "";
    }

    index = (hasParent ? index - 1 : index);
    return normalizePath((dir / this->subdirs[index]).string());
}

std::string DirectoryAdapter::GetLeafAt(size_t index) {
    if (this->ShowParentPath() && index == 0) {
        return "..";
    }

    return this->subdirs[index];
}

size_t DirectoryAdapter::IndexOf(const std::string& leaf) {
   for (size_t i = 0; i < this->subdirs.size(); i++) {
        if (this->subdirs[i] == leaf) {
            return i;
        }
    }

   return NO_INDEX;
}

size_t DirectoryAdapter::GetEntryCount() {
    size_t count = subdirs.size();
    return this->ShowParentPath() ? count + 1 : count;
}

void DirectoryAdapter::SetDotfilesVisible(bool visible) {
    if (showDotfiles != visible) {
        showDotfiles = visible;
        buildDirectoryList(dir, subdirs, showDotfiles);
    }
}

std::string DirectoryAdapter::GetParentPath() {
    if (dir.has_parent_path() &&
        normalizePath(this->dir) != normalizePath(this->rootDir))
    {
        return normalizePath(dir.parent_path().string());
    }

    return "";
}

std::string DirectoryAdapter::GetCurrentPath() {
    return normalizePath(dir.string());
}

void DirectoryAdapter::Refresh() {
    buildDirectoryList(dir, subdirs, showDotfiles);
}

bool DirectoryAdapter::ShowParentPath() {
    if (normalizePath(this->dir) == normalizePath(this->rootDir)
        && !this->allowEscapeRoot)
    {
        return false;
    }

    return dir.has_parent_path();
}

bool DirectoryAdapter::HasSubDirectories(size_t index) {
    bool hasParent = this->ShowParentPath();
    if (index == 0 && hasParent) {
        return true;
    }

    index = hasParent ? index - 1 : index;
    return hasSubdirectories(this->dir / this->subdirs[index], this->showDotfiles);
}

bool DirectoryAdapter::HasSubDirectories() {
    return hasSubdirectories(this->dir, this->showDotfiles);
}

IScrollAdapter::EntryPtr DirectoryAdapter::GetEntry(cursespp::ScrollableWindow* window, size_t index) {
    if (this->ShowParentPath()) {
        if (index == 0) {
            return IScrollAdapter::EntryPtr(new SingleLineEntry(".."));
        }
        --index;
    }

    auto text = text::Ellipsize(this->subdirs[index], this->GetWidth());
    return IScrollAdapter::EntryPtr(new SingleLineEntry(text));
}
<|endoftext|>


<commit_before>// Filename: SpongeLayerForceFunction.C
// Created on 28 Oct 2011 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "SpongeLayerForceFunction.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBAMR_config
#include <IBAMR_config.h>
#define included_IBAMR_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBAMR INCLUDES
#include <ibamr/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBAMR
{
/////////////////////////////// STATIC ///////////////////////////////////////

namespace
{
inline double
smooth_kernel(
    const double r)
{
    return std::abs(r) < 1.0 ? 0.5*(cos(M_PI*r)+1.0) : 0.0;
}// smooth_kernel
}

////////////////////////////// PUBLIC ///////////////////////////////////////

SpongeLayerForceFunction::SpongeLayerForceFunction(
    const std::string& object_name,
    const Pointer<Database> input_db,
    const INSHierarchyIntegrator* fluid_solver,
    Pointer<CartesianGridGeometry<NDIM> > grid_geometry)
    : CartGridFunction(object_name),
      d_forcing_enabled(SAMRAI::tbox::Array<bool>(NDIM)),
      d_width(0.0),
      d_fluid_solver(fluid_solver),
      d_grid_geometry(grid_geometry)
{
    if (input_db)
    {
        for (unsigned int location_index = 0; location_index < 2*NDIM; ++location_index)
        {
            for (unsigned int d = 0; d < NDIM; ++d) d_forcing_enabled[location_index][d] = false;
            std::ostringstream forcing_enabled_stream;
            forcing_enabled_stream << "forcing_enabled_" << location_index;
            const std::string forcing_enabled_key = forcing_enabled_stream.str();
            if (input_db->keyExists(forcing_enabled_key))
            {
                d_forcing_enabled[location_index] = input_db->getBoolArray(forcing_enabled_key);
            }
            std::ostringstream width_stream;
            width_stream << "width_" << location_index;
            const std::string width_key = width_stream.str();
            if (input_db->keyExists(width_key))
            {
                d_width[location_index] = input_db->getDouble(width_key);
            }
        }
    }
    return;
}// SpongeLayerForceFunction

SpongeLayerForceFunction::~SpongeLayerForceFunction()
{
    // intentionally blank
    return;
}// ~SpongeLayerForceFunction

bool
SpongeLayerForceFunction::isTimeDependent() const
{
    return true;
}// isTimeDependent

void
SpongeLayerForceFunction::setDataOnPatch(
    const int data_idx,
    Pointer<Variable<NDIM> > /*var*/,
    Pointer<Patch<NDIM> > patch,
    const double /*data_time*/,
    const bool initial_time,
    Pointer<PatchLevel<NDIM> > /*level*/)
{
    Pointer<PatchData<NDIM> > f_data = patch->getPatchData(data_idx);
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(f_data);
#endif
    Pointer<CellData<NDIM,double> > f_cc_data = f_data;
    Pointer<SideData<NDIM,double> > f_sc_data = f_data;
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(f_cc_data || f_sc_data);
#endif
    if (f_cc_data) f_cc_data->fillAll(0.0);
    if (f_sc_data) f_sc_data->fillAll(0.0);
    if (initial_time) return;
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    const double dt     = d_fluid_solver->getCurrentTimeStepSize();
    const double rho    = d_fluid_solver->getStokesSpecifications()->getRho();
    const double kappa  = cycle_num >= 0 ? 0.5*rho/dt : 0.0;
    Pointer<PatchData<NDIM> > u_current_data = patch->getPatchData(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getCurrentContext());
    Pointer<PatchData<NDIM> > u_new_data     = patch->getPatchData(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getNewContext()    );
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(u_current_data);
#endif
    if (f_cc_data) setDataOnPatchCell(f_data, u_current_data, u_new_data, kappa, patch);
    if (f_sc_data) setDataOnPatchSide(f_data, u_current_data, u_new_data, kappa, patch);
    return;
}// setDataOnPatch

/////////////////////////////// PROTECTED ////////////////////////////////////

/////////////////////////////// PRIVATE //////////////////////////////////////

void
SpongeLayerForceFunction::setDataOnPatchCell(
    Pointer<CellData<NDIM,double> > F_data,
    Pointer<CellData<NDIM,double> > U_current_data,
    Pointer<CellData<NDIM,double> > U_new_data,
    const double kappa,
    Pointer<Patch<NDIM> > patch)
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(F_data && U_current_data);
#endif
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    const Box<NDIM>& patch_box = patch->getBox();
    Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch->getPatchGeometry();
    const double* const dx = pgeom->getDx();
    const double* const x_lower = pgeom->getXLower();
    const double* const x_upper = pgeom->getXUpper();
    const IntVector<NDIM>& ratio = pgeom->getRatio();
    const Box<NDIM> domain_box = Box<NDIM>::refine(d_grid_geometry->getPhysicalDomain()[0],ratio);
    for (unsigned int location_index = 0; location_index < 2*NDIM; ++location_index)
    {
        const unsigned int axis = location_index / 2;
        const unsigned int side = location_index % 2;
        const bool is_lower     = side == 0;
        for (unsigned int d = 0; d < NDIM; ++d)
        {
            if (d_forcing_enabled[location_index][d] && pgeom->getTouchesRegularBoundary(axis,side))
            {
                Box<NDIM> bdry_box = domain_box;
                const int offset = static_cast<int>(d_width[location_index]/dx[axis]);
                if (is_lower)
                {
                    bdry_box.upper(axis) = domain_box.lower(axis)+offset;
                }
                else
                {
                    bdry_box.lower(axis) = domain_box.upper(axis)-offset;
                }
                for (Box<NDIM>::Iterator b(bdry_box*patch_box); b; b++)
                {
                    const Index<NDIM>& i = b();
                    const double U_current = U_current_data ? (*U_current_data)(i,d) : 0.0;
                    const double U_new     = U_new_data     ? (*U_new_data    )(i,d) : 0.0;
                    const double U = (cycle_num > 0) ? 0.5*(U_new+U_current) : U_current;
                    const double x = x_lower[axis] + dx[axis]*static_cast<double>(i(axis)-patch_box.lower(axis));
                    const double x_bdry = (is_lower ? x_lower[axis] : x_upper[axis]);
                    (*F_data)(i,d) = smooth_kernel((x-x_bdry)/d_width[location_index])*kappa*(0.0 - U);
                }
            }
        }
    }
    return;
}// setDataOnPatchCell

void
SpongeLayerForceFunction::setDataOnPatchSide(
    Pointer<SideData<NDIM,double> > F_data,
    Pointer<SideData<NDIM,double> > U_current_data,
    Pointer<SideData<NDIM,double> > U_new_data,
    const double kappa,
    Pointer<Patch<NDIM> > patch)
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(F_data && U_current_data);
#endif
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    const Box<NDIM>& patch_box = patch->getBox();
    Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch->getPatchGeometry();
    const double* const dx = pgeom->getDx();
    const double* const x_lower = pgeom->getXLower();
    const double* const x_upper = pgeom->getXUpper();
    const IntVector<NDIM>& ratio = pgeom->getRatio();
    const Box<NDIM> domain_box = Box<NDIM>::refine(d_grid_geometry->getPhysicalDomain()[0],ratio);
    for (unsigned int location_index = 0; location_index < 2*NDIM; ++location_index)
    {
        const unsigned int axis = location_index / 2;
        const unsigned int side = location_index % 2;
        const bool is_lower     = side == 0;
        for (unsigned int d = 0; d < NDIM; ++d)
        {
            if (d_forcing_enabled[location_index][d] && pgeom->getTouchesRegularBoundary(axis,side))
            {
                Box<NDIM> bdry_box = domain_box;
                const int offset = static_cast<int>(d_width[location_index]/dx[axis]);
                if (is_lower)
                {
                    bdry_box.upper(axis) = domain_box.lower(axis)+offset;
                }
                else
                {
                    bdry_box.lower(axis) = domain_box.upper(axis)-offset;
                }
                for (Box<NDIM>::Iterator b(SideGeometry<NDIM>::toSideBox(bdry_box*patch_box,d)); b; b++)
                {
                    const Index<NDIM>& i = b();
                    const SideIndex<NDIM> i_s(i, d, SideIndex<NDIM>::Lower);
                    const double U_current = U_current_data ? (*U_current_data)(i_s) : 0.0;
                    const double U_new     = U_new_data     ? (*U_new_data    )(i_s) : 0.0;
                    const double U = (cycle_num > 0) ? 0.5*(U_new+U_current) : U_current;
                    const double x = x_lower[axis] + dx[axis]*static_cast<double>(i(axis)-patch_box.lower(axis));
                    const double x_bdry = (is_lower ? x_lower[axis] : x_upper[axis]);
                    (*F_data)(i_s) = smooth_kernel((x-x_bdry)/d_width[location_index])*kappa*(0.0 - U);
                }
            }
        }
    }
    return;
}// setDataOnPatchSide

/////////////////////////////// NAMESPACE ////////////////////////////////////

} // namespace IBAMR

//////////////////////////////////////////////////////////////////////////////
<commit_msg>branch boyceg: fixed indexing error in SpongeLayerForceFunction<commit_after>// Filename: SpongeLayerForceFunction.C
// Created on 28 Oct 2011 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "SpongeLayerForceFunction.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBAMR_config
#include <IBAMR_config.h>
#define included_IBAMR_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBAMR INCLUDES
#include <ibamr/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBAMR
{
/////////////////////////////// STATIC ///////////////////////////////////////

namespace
{
inline double
smooth_kernel(
    const double r)
{
    return std::abs(r) < 1.0 ? 0.5*(cos(M_PI*r)+1.0) : 0.0;
}// smooth_kernel
}

////////////////////////////// PUBLIC ///////////////////////////////////////

SpongeLayerForceFunction::SpongeLayerForceFunction(
    const std::string& object_name,
    const Pointer<Database> input_db,
    const INSHierarchyIntegrator* fluid_solver,
    Pointer<CartesianGridGeometry<NDIM> > grid_geometry)
    : CartGridFunction(object_name),
      d_forcing_enabled(SAMRAI::tbox::Array<bool>(NDIM)),
      d_width(0.0),
      d_fluid_solver(fluid_solver),
      d_grid_geometry(grid_geometry)
{
    if (input_db)
    {
        for (unsigned int location_index = 0; location_index < 2*NDIM; ++location_index)
        {
            for (unsigned int d = 0; d < NDIM; ++d) d_forcing_enabled[location_index][d] = false;
            std::ostringstream forcing_enabled_stream;
            forcing_enabled_stream << "forcing_enabled_" << location_index;
            const std::string forcing_enabled_key = forcing_enabled_stream.str();
            if (input_db->keyExists(forcing_enabled_key))
            {
                d_forcing_enabled[location_index] = input_db->getBoolArray(forcing_enabled_key);
            }
            std::ostringstream width_stream;
            width_stream << "width_" << location_index;
            const std::string width_key = width_stream.str();
            if (input_db->keyExists(width_key))
            {
                d_width[location_index] = input_db->getDouble(width_key);
            }
        }
    }
    return;
}// SpongeLayerForceFunction

SpongeLayerForceFunction::~SpongeLayerForceFunction()
{
    // intentionally blank
    return;
}// ~SpongeLayerForceFunction

bool
SpongeLayerForceFunction::isTimeDependent() const
{
    return true;
}// isTimeDependent

void
SpongeLayerForceFunction::setDataOnPatch(
    const int data_idx,
    Pointer<Variable<NDIM> > /*var*/,
    Pointer<Patch<NDIM> > patch,
    const double /*data_time*/,
    const bool initial_time,
    Pointer<PatchLevel<NDIM> > /*level*/)
{
    Pointer<PatchData<NDIM> > f_data = patch->getPatchData(data_idx);
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(f_data);
#endif
    Pointer<CellData<NDIM,double> > f_cc_data = f_data;
    Pointer<SideData<NDIM,double> > f_sc_data = f_data;
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(f_cc_data || f_sc_data);
#endif
    if (f_cc_data) f_cc_data->fillAll(0.0);
    if (f_sc_data) f_sc_data->fillAll(0.0);
    if (initial_time) return;
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    const double dt     = d_fluid_solver->getCurrentTimeStepSize();
    const double rho    = d_fluid_solver->getStokesSpecifications()->getRho();
    const double kappa  = cycle_num >= 0 ? 0.5*rho/dt : 0.0;
    Pointer<PatchData<NDIM> > u_current_data = patch->getPatchData(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getCurrentContext());
    Pointer<PatchData<NDIM> > u_new_data     = patch->getPatchData(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getNewContext()    );
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(u_current_data);
#endif
    if (f_cc_data) setDataOnPatchCell(f_data, u_current_data, u_new_data, kappa, patch);
    if (f_sc_data) setDataOnPatchSide(f_data, u_current_data, u_new_data, kappa, patch);
    return;
}// setDataOnPatch

/////////////////////////////// PROTECTED ////////////////////////////////////

/////////////////////////////// PRIVATE //////////////////////////////////////

void
SpongeLayerForceFunction::setDataOnPatchCell(
    Pointer<CellData<NDIM,double> > F_data,
    Pointer<CellData<NDIM,double> > U_current_data,
    Pointer<CellData<NDIM,double> > U_new_data,
    const double kappa,
    Pointer<Patch<NDIM> > patch)
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(F_data && U_current_data);
#endif
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    const Box<NDIM>& patch_box = patch->getBox();
    Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch->getPatchGeometry();
    const double* const dx = pgeom->getDx();
    const double* const x_lower = pgeom->getXLower();
    const double* const x_upper = pgeom->getXUpper();
    const IntVector<NDIM>& ratio = pgeom->getRatio();
    const Box<NDIM> domain_box = Box<NDIM>::refine(d_grid_geometry->getPhysicalDomain()[0],ratio);
    for (unsigned int location_index = 0; location_index < 2*NDIM; ++location_index)
    {
        const unsigned int axis = location_index / 2;
        const unsigned int side = location_index % 2;
        const bool is_lower     = side == 0;
        for (unsigned int d = 0; d < NDIM; ++d)
        {
            if (d_forcing_enabled[location_index][d] && pgeom->getTouchesRegularBoundary(axis,side))
            {
                Box<NDIM> bdry_box = domain_box;
                const int offset = static_cast<int>(d_width[location_index]/dx[axis]);
                if (is_lower)
                {
                    bdry_box.upper(axis) = domain_box.lower(axis)+offset;
                }
                else
                {
                    bdry_box.lower(axis) = domain_box.upper(axis)-offset;
                }
                for (Box<NDIM>::Iterator b(bdry_box*patch_box); b; b++)
                {
                    const Index<NDIM>& i = b();
                    const double U_current = U_current_data ? (*U_current_data)(i,d) : 0.0;
                    const double U_new     = U_new_data     ? (*U_new_data    )(i,d) : 0.0;
                    const double U = (cycle_num > 0) ? 0.5*(U_new+U_current) : U_current;
                    const double x = x_lower[axis] + dx[axis]*(static_cast<double>(i(axis)-patch_box.lower(axis))+0.5);
                    const double x_bdry = (is_lower ? x_lower[axis] : x_upper[axis]);
                    (*F_data)(i,d) = smooth_kernel((x-x_bdry)/d_width[location_index])*kappa*(0.0 - U);
                }
            }
        }
    }
    return;
}// setDataOnPatchCell

void
SpongeLayerForceFunction::setDataOnPatchSide(
    Pointer<SideData<NDIM,double> > F_data,
    Pointer<SideData<NDIM,double> > U_current_data,
    Pointer<SideData<NDIM,double> > U_new_data,
    const double kappa,
    Pointer<Patch<NDIM> > patch)
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(F_data && U_current_data);
#endif
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    const Box<NDIM>& patch_box = patch->getBox();
    Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch->getPatchGeometry();
    const double* const dx = pgeom->getDx();
    const double* const x_lower = pgeom->getXLower();
    const double* const x_upper = pgeom->getXUpper();
    const IntVector<NDIM>& ratio = pgeom->getRatio();
    const Box<NDIM> domain_box = Box<NDIM>::refine(d_grid_geometry->getPhysicalDomain()[0],ratio);
    for (unsigned int location_index = 0; location_index < 2*NDIM; ++location_index)
    {
        const unsigned int axis = location_index / 2;
        const unsigned int side = location_index % 2;
        const bool is_lower     = side == 0;
        for (unsigned int d = 0; d < NDIM; ++d)
        {
            if (d_forcing_enabled[location_index][d] && pgeom->getTouchesRegularBoundary(axis,side))
            {
                Box<NDIM> bdry_box = domain_box;
                const int offset = static_cast<int>(d_width[location_index]/dx[axis]);
                if (is_lower)
                {
                    bdry_box.upper(axis) = domain_box.lower(axis)+offset;
                }
                else
                {
                    bdry_box.lower(axis) = domain_box.upper(axis)-offset;
                }
                for (Box<NDIM>::Iterator b(SideGeometry<NDIM>::toSideBox(bdry_box*patch_box,d)); b; b++)
                {
                    const Index<NDIM>& i = b();
                    const SideIndex<NDIM> i_s(i, d, SideIndex<NDIM>::Lower);
                    const double U_current = U_current_data ? (*U_current_data)(i_s) : 0.0;
                    const double U_new     = U_new_data     ? (*U_new_data    )(i_s) : 0.0;
                    const double U = (cycle_num > 0) ? 0.5*(U_new+U_current) : U_current;
                    const double x = x_lower[axis] + dx[axis]*static_cast<double>(i(axis)-patch_box.lower(axis));
                    const double x_bdry = (is_lower ? x_lower[axis] : x_upper[axis]);
                    (*F_data)(i_s) = smooth_kernel((x-x_bdry)/d_width[location_index])*kappa*(0.0 - U);
                }
            }
        }
    }
    return;
}// setDataOnPatchSide

/////////////////////////////// NAMESPACE ////////////////////////////////////

} // namespace IBAMR

//////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include <iostream>
#include <math.h>
#include "detector.h"
#include "toolbox.h"
#include "io.h"
using namespace std;
using namespace arma;
using namespace detector;
using namespace toolbox;

double CDetector::d; 				// (m) detector distance
double CDetector::pix_width;		// (m)
double CDetector::pix_height;		// (m)
int CDetector::px;					// number of pixels in x
int CDetector::py;					// number of pixels in y
int CDetector::numPix;				// total number of pixels
double CDetector::cx;				// center of detector in x
double CDetector::cy;				// center of detector in y
fmat CDetector::dp;					// diffraction pattern
fmat CDetector::q_x;
fmat CDetector::q_y;
fmat CDetector::q_z;
fcube CDetector::q_xyz; // slow? perhaps waste of memory
fmat CDetector::q_mod;
fmat CDetector::solidAngle;
fmat CDetector::thomson;
uvec CDetector::badpixmap;//sp_imat CDetector::badpixmap;
uvec CDetector::goodpixmap;

CDetector::CDetector (){
    d = 0;
    pix_width = 0;
    pix_height = 0;
    px = 0;
    py = 0;
    numPix = 0;
    cx = 0;
    cy = 0;
	//cout << "init detector" << endl;
}

void CDetector::set_detector_dist(double dist){
	d = dist;
}

double CDetector::get_detector_dist(){
	cout << "dist: " << d << endl;
	return d;
}

void CDetector::set_pix_width(double width){
	pix_width = width;
}

double CDetector::get_pix_width(){
	return pix_width;
}

void CDetector::set_pix_height(double height){
	pix_height = height;
}

double CDetector::get_pix_height(){
	return pix_height;
}

void CDetector::set_numPix_x(int x){
	px = x;
}

int CDetector::get_numPix_x(){
	return px;
}

void CDetector::set_numPix_y(int y){
	py = y;
}

void CDetector::set_numPix(int y,int x){
	py = y;
	px = x;
	numPix = py*px;
}

int CDetector::get_numPix_y(){
	return py;
}

void CDetector::set_center_x(double x){
	cx = x;
}

double CDetector::get_center_x(){
	return cx;
}

void CDetector::set_center_y(double y){
	cy = y;
}

double CDetector::get_center_y(){
	return cy;
}

uvec CDetector::get_goodPixelMap(){
    return goodpixmap;
}

uvec CDetector::get_badPixelMap(){
    return badpixmap;
}

void CDetector::set_pixelMap(string x){
	fmat temp;
	if (x.empty()) { // badpixelmap is not specified
		if (py > 0 && px > 0) {
			temp.zeros(py,px);
		} else {
			cout << "Please set detector dimensions before calling set_pixelMap" << endl;
			exit(0);
		}
	} else { // load badpixelmap
		temp = load_asciiImage(x);
	}
	badpixmap = find(temp == 1);
	//badpixmap.print("badpix: ");
	goodpixmap = find(temp == 0);
	/*
	badpixmap.copy_size(temp);
	for (int i = 0; i < temp.n_rows; i++) {
		for (int j = 0; j < temp.n_cols; j++) {
		    if (temp(i,j) == 1) {
	            badpixmap(i,j) = 1;
	        }
	    }
	}
	badpixmap.print("badpixmap: ");
	// Wrong way to access sparse elements
	cout << badpixmap(0) << endl;
	cout << badpixmap(1) << endl;
	// Correct way to access sparse elements
	sp_imat::iterator a = badpixmap.begin();
    sp_imat::iterator b = badpixmap.end();
    for(sp_imat::iterator i=a; i!=b; ++i) {
        cout << *i << endl;
    }
    */
}

void CDetector::apply_badPixels() {
    //fmat& myDP = in[0];
    uvec::iterator a = badpixmap.begin();
    uvec::iterator b = badpixmap.end();
    for(uvec::iterator i=a; i!=b; ++i) {
        //cout << *i << endl;
        dp(*i) = 0;
    }
}

void CDetector::apply_badPixels(fmat *x) {
	fmat& myDP = x[0];
    uvec::iterator a = badpixmap.begin();
    uvec::iterator b = badpixmap.end();
    for(uvec::iterator i=a; i!=b; ++i) {
        myDP(*i) = 0;
    }
}

// set beam object variables and assign q to each pixel
void CDetector::init_dp( beam::CBeam *beam ){
    // this bit should be set already, get rid of this?
	set_detector_dist(d);
	set_pix_width(pix_width);
	set_pix_height(pix_height);
	set_numPix(py,px);
	set_center_x(cx);
	set_center_y(cy);

	// Used for single particle. Set 1/pix_width=9090 for LCLS
	q_xyz.zeros(py,px,3);
	float rx, ry, r, twotheta, az;
	float pixDist, alpha;
	solidAngle.zeros(py,px);
	fmat twoTheta(py,px);
	for (int ind_x = 0; ind_x < px; ind_x++) {
		for (int ind_y = 0; ind_y < py; ind_y++) {
			rx = (ind_x - cx) * pix_width; // equivalent to dividing by pixel resolution
			ry = (ind_y - cy) * pix_width;
			r = sqrt(pow(rx,2)+pow(ry,2));
			twotheta = atan2(r,d);
			twoTheta(ind_y,ind_x) = twotheta;
			az = atan2(ry,rx);
			q_xyz(ind_y,ind_x,0) = beam->get_wavenumber() * sin(twotheta)*cos(az);
			q_xyz(ind_y,ind_x,1) = beam->get_wavenumber() * sin(twotheta)*sin(az);
			q_xyz(ind_y,ind_x,2) = beam->get_wavenumber() * (cos(twotheta) - 1.0);

			// Analytical formula of solid angle (Zaluzec2014)
			pixDist = sqrt(pow(rx,2) + pow(ry,2) + pow(d,2)); // distance from interaction to pixel center in real space
			alpha = atan(pix_width/(2*pixDist));
			solidAngle(ind_y,ind_x) = 4 * asin( pow(sin(alpha),2) );
		}
	}
	q_mod = CToolbox::mag(q_xyz);

	double re = 2.81793870e-15;			// classical electron radius (m)
	// Polarization factor, cos^2 mu + sin^2 mu * cos^2(2theta)
	double mu; // polarization angle
	string electricFieldPlane = "horizontal";
	if (electricFieldPlane == "horizontal") {
		mu = 0;
	} else if (electricFieldPlane == "vertical") {
		mu = datum::pi/2;
	} else {
		// unpolarized
		mu = datum::pi/4;
	}
	fmat polarizationFactor = ( pow(cos(mu),2) + pow(sin(mu),2)*pow(cos(twoTheta),2) );
	thomson = pow(re,2) * polarizationFactor;
}

void CDetector::set_param(Packet *x){
	umat temp(x->dp, x->py, x->px, false, true);
	dp = conv_to<fmat>::from(trans(temp));
	d = x->d;
	pix_width = x->pix_width;
	pix_height = x->pix_height;
	py = x->py;
	px = x->px;
	cx = ((double) px-1)/2;			// this can be user defined
	cy = ((double) py-1)/2;			// this can be user defined
}

<commit_msg>Cleaned up detector object<commit_after>#include <iostream>
#include <math.h>
#include "detector.h"
#include "toolbox.h"
#include "io.h"
using namespace std;
using namespace arma;
using namespace detector;
using namespace toolbox;

double CDetector::d; 				// (m) detector distance
double CDetector::pix_width;		// (m)
double CDetector::pix_height;		// (m)
int CDetector::px;					// number of pixels in x
int CDetector::py;					// number of pixels in y
int CDetector::numPix;				// total number of pixels (px*py)
double CDetector::cx;				// center of detector in x
double CDetector::cy;				// center of detector in y
fmat CDetector::dp;					// diffraction pattern
fmat CDetector::q_x;				// pixel reciprocal space in x
fmat CDetector::q_y;				// pixel reciprocal space in y
fmat CDetector::q_z;				// pixel reciprocal space in z
fcube CDetector::q_xyz; // slow? perhaps waste of memory
fmat CDetector::q_mod;				// pixel reciprocal space
fmat CDetector::solidAngle;			// solid angle
fmat CDetector::thomson;			// Thomson scattering
uvec CDetector::badpixmap;			// bad pixel map (bad = 1)
uvec CDetector::goodpixmap;			// good pixel map (good = 1)

CDetector::CDetector (){
    d = 0;
    pix_width = 0;
    pix_height = 0;
    px = 0;
    py = 0;
    numPix = 0;
    cx = 0;
    cy = 0;
}

void CDetector::set_detector_dist(double dist){
	d = dist;
}

double CDetector::get_detector_dist(){
	cout << "dist: " << d << endl;
	return d;
}

void CDetector::set_pix_width(double width){
	pix_width = width;
}

double CDetector::get_pix_width(){
	return pix_width;
}

void CDetector::set_pix_height(double height){
	pix_height = height;
}

double CDetector::get_pix_height(){
	return pix_height;
}

void CDetector::set_numPix_x(int x){
	px = x;
}

int CDetector::get_numPix_x(){
	return px;
}

void CDetector::set_numPix_y(int y){
	py = y;
}

void CDetector::set_numPix(int y,int x){
	py = y;
	px = x;
	numPix = py*px;
}

int CDetector::get_numPix_y(){
	return py;
}

void CDetector::set_center_x(double x){
	cx = x;
}

double CDetector::get_center_x(){
	return cx;
}

void CDetector::set_center_y(double y){
	cy = y;
}

double CDetector::get_center_y(){
	return cy;
}

uvec CDetector::get_goodPixelMap(){
    return goodpixmap;
}

uvec CDetector::get_badPixelMap(){
    return badpixmap;
}

void CDetector::set_pixelMap(string x){
	fmat temp;
	if (x.empty()) { // badpixelmap is not specified
		if (py > 0 && px > 0) {
			temp.zeros(py,px);
		} else {
			cout << "Please set detector dimensions before calling set_pixelMap" << endl;
			exit(0);
		}
	} else { // load badpixelmap
		temp = load_asciiImage(x);
	}
	badpixmap = find(temp == 1);
	goodpixmap = find(temp == 0);
}

void CDetector::apply_badPixels() {
    uvec::iterator a = badpixmap.begin();
    uvec::iterator b = badpixmap.end();
    for(uvec::iterator i=a; i!=b; ++i) {
        dp(*i) = 0;
    }
}

void CDetector::apply_badPixels(fmat *x) {
	fmat& myDP = x[0];
    uvec::iterator a = badpixmap.begin();
    uvec::iterator b = badpixmap.end();
    for(uvec::iterator i=a; i!=b; ++i) {
        myDP(*i) = 0;
    }
}

// set beam object variables and assign q to each pixel
void CDetector::init_dp( beam::CBeam *beam ){
    // this bit should be set already, get rid of this?
	set_detector_dist(d);
	set_pix_width(pix_width);
	set_pix_height(pix_height);
	set_numPix(py,px);
	set_center_x(cx);
	set_center_y(cy);

	// Used for single particle. Set 1/pix_width=9090 for LCLS
	q_xyz.zeros(py,px,3);
	float rx, ry, r, twotheta, az;
	float pixDist, alpha;
	solidAngle.zeros(py,px);
	fmat twoTheta(py,px);
	for (int ind_x = 0; ind_x < px; ind_x++) {
		for (int ind_y = 0; ind_y < py; ind_y++) {
			rx = (ind_x - cx) * pix_width; // equivalent to dividing by pixel resolution
			ry = (ind_y - cy) * pix_width;
			r = sqrt(pow(rx,2)+pow(ry,2));
			twotheta = atan2(r,d);
			twoTheta(ind_y,ind_x) = twotheta;
			az = atan2(ry,rx);
			q_xyz(ind_y,ind_x,0) = beam->get_wavenumber() * sin(twotheta)*cos(az);
			q_xyz(ind_y,ind_x,1) = beam->get_wavenumber() * sin(twotheta)*sin(az);
			q_xyz(ind_y,ind_x,2) = beam->get_wavenumber() * (cos(twotheta) - 1.0);

			// Analytical formula of solid angle (Zaluzec2014)
			pixDist = sqrt(pow(rx,2) + pow(ry,2) + pow(d,2)); // distance from interaction to pixel center in real space
			alpha = atan(pix_width/(2*pixDist));
			solidAngle(ind_y,ind_x) = 4 * asin( pow(sin(alpha),2) );
		}
	}
	q_mod = CToolbox::mag(q_xyz);

	double const re = 2.81793870e-15;			// classical electron radius (m)
	// Polarization factor, cos^2 mu + sin^2 mu * cos^2(2theta)
	double mu; // polarization angle
	string electricFieldPlane = "horizontal";
	if (electricFieldPlane == "horizontal") {
		mu = 0;
	} else if (electricFieldPlane == "vertical") {
		mu = datum::pi/2;
	} else {
		// unpolarized
		mu = datum::pi/4;
	}
	fmat polarizationFactor = ( pow(cos(mu),2) + pow(sin(mu),2)*pow(cos(twoTheta),2) );
	thomson = pow(re,2) * polarizationFactor;
}

void CDetector::set_param(Packet *x){
	umat temp(x->dp, x->py, x->px, false, true);
	dp = conv_to<fmat>::from(trans(temp));
	d = x->d;
	pix_width = x->pix_width;
	pix_height = x->pix_height;
	py = x->py;
	px = x->px;
	cx = ((double) px-1)/2;			// this can be user defined
	cy = ((double) py-1)/2;			// this can be user defined
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: addrdlg.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 22:48:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#ifdef SW_DLLIMPLEMENTATION
#undef SW_DLLIMPLEMENTATION
#endif

#include "addrdlg.hxx"

//CHINA001 #ifndef _SVX_OPTGENRL_HXX //autogen
//CHINA001 #include <svx/optgenrl.hxx>
//CHINA001 #endif
#ifndef _SVX_DIALOG_HXX
#include <svx/svxdlg.hxx>
#endif
#ifndef _SFX_HRC
#include <sfx2/sfx.hrc>
#endif

/****************************************************************************
Ctor
****************************************************************************/

SwAddrDlg::SwAddrDlg(Window* pParent, SfxItemSet& rSet ) :

    SfxSingleTabDialog(pParent, rSet, 0)

{
    // TabPage erzeugen
    //CHINA001 SvxGeneralTabPage* pPage = (SvxGeneralTabPage*) SvxGeneralTabPage::Create(this, rSet);
    SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
    DBG_ASSERT(pFact, "Dialogdiet fail!");//CHINA001
    ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SFXPAGE_GENERAL );
    if ( fnCreatePage )
    {
        SfxTabPage* pPage = (*fnCreatePage)( this, rSet );
        SetTabPage(pPage);
    }
}

/****************************************************************************
Dtor
****************************************************************************/

__EXPORT SwAddrDlg::~SwAddrDlg()
{
}

<commit_msg>INTEGRATION: CWS swwarnings (1.7.222); FILE MERGED 2007/04/13 12:17:51 tl 1.7.222.2: #i69287# binfilter related comments removed 2007/03/26 12:08:54 tl 1.7.222.1: #i69287# warning-free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: addrdlg.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 11:36:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#ifdef SW_DLLIMPLEMENTATION
#undef SW_DLLIMPLEMENTATION
#endif

#include "addrdlg.hxx"

#ifndef _SVX_DIALOG_HXX
#include <svx/svxdlg.hxx>
#endif
#ifndef _SFX_HRC
#include <sfx2/sfx.hrc>
#endif

/****************************************************************************
Ctor
****************************************************************************/

SwAddrDlg::SwAddrDlg(Window* pParent, SfxItemSet& rSet ) :

    SfxSingleTabDialog(pParent, rSet, 0)

{
    // TabPage erzeugen
    SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
    DBG_ASSERT(pFact, "Dialogdiet fail!");
    ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SFXPAGE_GENERAL );
    if ( fnCreatePage )
    {
        SfxTabPage* pPage2 = (*fnCreatePage)( this, rSet );
        SetTabPage(pPage2);
    }
}

/****************************************************************************
Dtor
****************************************************************************/

__EXPORT SwAddrDlg::~SwAddrDlg()
{
}

<|endoftext|>


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

/**
 * \file opt_array_splitting.cpp
 *
 * If an array is always dereferenced with a constant index, then
 * split it apart into its elements, making it more amenable to other
 * optimization passes.
 *
 * This skips uniform/varying arrays, which would need careful
 * handling due to their ir->location fields tying them to the GL API
 * and other shader stages.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_print_visitor.h"
#include "glsl_types.h"

static bool debug = false;

namespace opt_array_splitting {

class variable_entry : public exec_node
{
public:
   variable_entry(ir_variable *var)
   {
      this->var = var;
      this->whole_array_access = 0;
      this->declaration = false;
      this->components = NULL;
      this->mem_ctx = NULL;
      if (var->type->is_array())
	 this->size = var->type->length;
      else
	 this->size = var->type->matrix_columns;
   }

   ir_variable *var; /* The key: the variable's pointer. */
   unsigned size; /* array length or matrix columns */

   /** Number of times the variable is referenced, including assignments. */
   unsigned whole_array_access;

   bool declaration; /* If the variable had a decl in the instruction stream */

   ir_variable **components;

   /** ralloc_parent(this->var) -- the shader's talloc context. */
   void *mem_ctx;
};

} /* namespace */
using namespace opt_array_splitting;

/**
 * This class does a walk over the tree, coming up with the set of
 * variables that could be split by looking to see if they are arrays
 * that are only ever constant-index dereferenced.
 */
class ir_array_reference_visitor : public ir_hierarchical_visitor {
public:
   ir_array_reference_visitor(void)
   {
      this->mem_ctx = ralloc_context(NULL);
      this->variable_list.make_empty();
   }

   ~ir_array_reference_visitor(void)
   {
      ralloc_free(mem_ctx);
   }

   bool get_split_list(exec_list *instructions, bool linked);

   virtual ir_visitor_status visit(ir_variable *);
   virtual ir_visitor_status visit(ir_dereference_variable *);
   virtual ir_visitor_status visit_enter(ir_dereference_array *);

   variable_entry *get_variable_entry(ir_variable *var);

   /* List of variable_entry */
   exec_list variable_list;

   void *mem_ctx;
};

variable_entry *
ir_array_reference_visitor::get_variable_entry(ir_variable *var)
{
   assert(var);

   if (var->mode != ir_var_auto &&
       var->mode != ir_var_temporary)
      return NULL;

   if (!(var->type->is_array() || var->type->is_matrix()))
      return NULL;

   /* If the array hasn't been sized yet, we can't split it.  After
    * linking, this should be resolved.
    */
   if (var->type->is_array() && var->type->length == 0)
      return NULL;

   foreach_iter(exec_list_iterator, iter, this->variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      if (entry->var == var)
	 return entry;
   }

   variable_entry *entry = new(mem_ctx) variable_entry(var);
   this->variable_list.push_tail(entry);
   return entry;
}

ir_visitor_status
ir_array_reference_visitor::visit(ir_variable *ir)
{
   variable_entry *entry = this->get_variable_entry(ir);

   if (entry)
      entry->declaration = true;

   return visit_continue;
}

ir_visitor_status
ir_array_reference_visitor::visit(ir_dereference_variable *ir)
{
   variable_entry *entry = this->get_variable_entry(ir->var);

   /* If we made it to here, then the dereference of this array didn't
    * have a constant index (see the visit_continue_with_parent
    * below), so we can't split the variable.
    */
   if (entry)
      entry->whole_array_access++;

   return visit_continue;
}

ir_visitor_status
ir_array_reference_visitor::visit_enter(ir_dereference_array *ir)
{
   ir_dereference_variable *deref = ir->array->as_dereference_variable();
   if (!deref)
      return visit_continue;

   variable_entry *entry = this->get_variable_entry(deref->var);

   if (entry && !ir->array_index->as_constant())
      entry->whole_array_access++;

   return visit_continue_with_parent;
}

bool
ir_array_reference_visitor::get_split_list(exec_list *instructions,
					   bool linked)
{
   visit_list_elements(this, instructions);

   /* If the shaders aren't linked yet, we can't mess with global
    * declarations, which need to be matched by name across shaders.
    */
   if (!linked) {
      foreach_list(node, instructions) {
	 ir_variable *var = ((ir_instruction *)node)->as_variable();
	 if (var) {
	    variable_entry *entry = get_variable_entry(var);
	    if (entry)
	       entry->remove();
	 }
      }
   }

   /* Trim out variables we found that we can't split. */
   foreach_iter(exec_list_iterator, iter, variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();

      if (debug) {
	 printf("array %s@%p: decl %d, whole_access %d\n",
		entry->var->name, (void *) entry->var, entry->declaration,
		entry->whole_array_access);
      }

      if (!entry->declaration || entry->whole_array_access) {
	 entry->remove();
      }
   }

   return !variable_list.is_empty();
}

/**
 * This class rewrites the dereferences of arrays that have been split
 * to use the newly created ir_variables for each component.
 */
class ir_array_splitting_visitor : public ir_rvalue_visitor {
public:
   ir_array_splitting_visitor(exec_list *vars)
   {
      this->variable_list = vars;
   }

   virtual ~ir_array_splitting_visitor()
   {
   }

   virtual ir_visitor_status visit_leave(ir_assignment *);

   void split_deref(ir_dereference **deref);
   void handle_rvalue(ir_rvalue **rvalue);
   variable_entry *get_splitting_entry(ir_variable *var);

   exec_list *variable_list;
};

variable_entry *
ir_array_splitting_visitor::get_splitting_entry(ir_variable *var)
{
   assert(var);

   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      if (entry->var == var) {
	 return entry;
      }
   }

   return NULL;
}

void
ir_array_splitting_visitor::split_deref(ir_dereference **deref)
{
   ir_dereference_array *deref_array = (*deref)->as_dereference_array();
   if (!deref_array)
      return;

   ir_dereference_variable *deref_var = deref_array->array->as_dereference_variable();
   if (!deref_var)
      return;
   ir_variable *var = deref_var->var;

   variable_entry *entry = get_splitting_entry(var);
   if (!entry)
      return;

   ir_constant *constant = deref_array->array_index->as_constant();
   assert(constant);

   if (constant->value.i[0] < (int)entry->size) {
      *deref = new(entry->mem_ctx)
	 ir_dereference_variable(entry->components[constant->value.i[0]]);
   } else {
      /* There was a constant array access beyond the end of the
       * array.  This might have happened due to constant folding
       * after the initial parse.  This produces an undefined value,
       * but shouldn't crash.  Just give them an uninitialized
       * variable.
       */
      ir_variable *temp = new(entry->mem_ctx) ir_variable(deref_array->type,
							  "undef",
							  ir_var_temporary);
      entry->components[0]->insert_before(temp);
      *deref = new(entry->mem_ctx) ir_dereference_variable(temp);
   }
}

void
ir_array_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_dereference *deref = (*rvalue)->as_dereference();

   if (!deref)
      return;

   split_deref(&deref);
   *rvalue = deref;
}

ir_visitor_status
ir_array_splitting_visitor::visit_leave(ir_assignment *ir)
{
   /* The normal rvalue visitor skips the LHS of assignments, but we
    * need to process those just the same.
    */
   ir_rvalue *lhs = ir->lhs;

   handle_rvalue(&lhs);
   ir->lhs = lhs->as_dereference();

   ir->lhs->accept(this);

   handle_rvalue(&ir->rhs);
   ir->rhs->accept(this);

   if (ir->condition) {
      handle_rvalue(&ir->condition);
      ir->condition->accept(this);
   }

   return visit_continue;
}

bool
optimize_split_arrays(exec_list *instructions, bool linked)
{
   ir_array_reference_visitor refs;
   if (!refs.get_split_list(instructions, linked))
      return false;

   void *mem_ctx = ralloc_context(NULL);

   /* Replace the decls of the arrays to be split with their split
    * components.
    */
   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      const struct glsl_type *type = entry->var->type;
      const struct glsl_type *subtype;

      if (type->is_matrix())
	 subtype = type->column_type();
      else
	 subtype = type->fields.array;

      entry->mem_ctx = ralloc_parent(entry->var);

      entry->components = ralloc_array(mem_ctx,
				       ir_variable *,
				       entry->size);

      for (unsigned int i = 0; i < entry->size; i++) {
	 const char *name = ralloc_asprintf(mem_ctx, "%s_%d",
					    entry->var->name, i);

	 entry->components[i] =
	    new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary);
	 entry->var->insert_before(entry->components[i]);
      }

      entry->var->remove();
   }

   ir_array_splitting_visitor split(&refs.variable_list);
   visit_list_elements(&split, instructions);

   if (debug)
      _mesa_print_ir(instructions, NULL);

   ralloc_free(mem_ctx);

   return true;

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

/**
 * \file opt_array_splitting.cpp
 *
 * If an array is always dereferenced with a constant index, then
 * split it apart into its elements, making it more amenable to other
 * optimization passes.
 *
 * This skips uniform/varying arrays, which would need careful
 * handling due to their ir->location fields tying them to the GL API
 * and other shader stages.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_print_visitor.h"
#include "glsl_types.h"

static bool debug = false;

namespace opt_array_splitting {

class variable_entry : public exec_node
{
public:
   variable_entry(ir_variable *var)
   {
      this->var = var;
      this->split = true;
      this->declaration = false;
      this->components = NULL;
      this->mem_ctx = NULL;
      if (var->type->is_array())
	 this->size = var->type->length;
      else
	 this->size = var->type->matrix_columns;
   }

   ir_variable *var; /* The key: the variable's pointer. */
   unsigned size; /* array length or matrix columns */

   /** Whether this array should be split or not. */
   bool split;

   bool declaration; /* If the variable had a decl in the instruction stream */

   ir_variable **components;

   /** ralloc_parent(this->var) -- the shader's talloc context. */
   void *mem_ctx;
};

} /* namespace */
using namespace opt_array_splitting;

/**
 * This class does a walk over the tree, coming up with the set of
 * variables that could be split by looking to see if they are arrays
 * that are only ever constant-index dereferenced.
 */
class ir_array_reference_visitor : public ir_hierarchical_visitor {
public:
   ir_array_reference_visitor(void)
   {
      this->mem_ctx = ralloc_context(NULL);
      this->variable_list.make_empty();
   }

   ~ir_array_reference_visitor(void)
   {
      ralloc_free(mem_ctx);
   }

   bool get_split_list(exec_list *instructions, bool linked);

   virtual ir_visitor_status visit(ir_variable *);
   virtual ir_visitor_status visit(ir_dereference_variable *);
   virtual ir_visitor_status visit_enter(ir_dereference_array *);

   variable_entry *get_variable_entry(ir_variable *var);

   /* List of variable_entry */
   exec_list variable_list;

   void *mem_ctx;
};

variable_entry *
ir_array_reference_visitor::get_variable_entry(ir_variable *var)
{
   assert(var);

   if (var->mode != ir_var_auto &&
       var->mode != ir_var_temporary)
      return NULL;

   if (!(var->type->is_array() || var->type->is_matrix()))
      return NULL;

   /* If the array hasn't been sized yet, we can't split it.  After
    * linking, this should be resolved.
    */
   if (var->type->is_array() && var->type->length == 0)
      return NULL;

   foreach_iter(exec_list_iterator, iter, this->variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      if (entry->var == var)
	 return entry;
   }

   variable_entry *entry = new(mem_ctx) variable_entry(var);
   this->variable_list.push_tail(entry);
   return entry;
}

ir_visitor_status
ir_array_reference_visitor::visit(ir_variable *ir)
{
   variable_entry *entry = this->get_variable_entry(ir);

   if (entry)
      entry->declaration = true;

   return visit_continue;
}

ir_visitor_status
ir_array_reference_visitor::visit(ir_dereference_variable *ir)
{
   variable_entry *entry = this->get_variable_entry(ir->var);

   /* If we made it to here without seeing an ir_dereference_array,
    * then the dereference of this array didn't have a constant index
    * (see the visit_continue_with_parent below), so we can't split
    * the variable.
    */
   if (entry)
      entry->split = false;

   return visit_continue;
}

ir_visitor_status
ir_array_reference_visitor::visit_enter(ir_dereference_array *ir)
{
   ir_dereference_variable *deref = ir->array->as_dereference_variable();
   if (!deref)
      return visit_continue;

   variable_entry *entry = this->get_variable_entry(deref->var);

   /* If the access to the array has a variable index, we wouldn't
    * know which split variable this dereference should go to.
    */
   if (entry && !ir->array_index->as_constant())
      entry->split = false;

   return visit_continue_with_parent;
}

bool
ir_array_reference_visitor::get_split_list(exec_list *instructions,
					   bool linked)
{
   visit_list_elements(this, instructions);

   /* If the shaders aren't linked yet, we can't mess with global
    * declarations, which need to be matched by name across shaders.
    */
   if (!linked) {
      foreach_list(node, instructions) {
	 ir_variable *var = ((ir_instruction *)node)->as_variable();
	 if (var) {
	    variable_entry *entry = get_variable_entry(var);
	    if (entry)
	       entry->remove();
	 }
      }
   }

   /* Trim out variables we found that we can't split. */
   foreach_iter(exec_list_iterator, iter, variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();

      if (debug) {
	 printf("array %s@%p: decl %d, split %d\n",
		entry->var->name, (void *) entry->var, entry->declaration,
		entry->split);
      }

      if (!(entry->declaration && entry->split)) {
	 entry->remove();
      }
   }

   return !variable_list.is_empty();
}

/**
 * This class rewrites the dereferences of arrays that have been split
 * to use the newly created ir_variables for each component.
 */
class ir_array_splitting_visitor : public ir_rvalue_visitor {
public:
   ir_array_splitting_visitor(exec_list *vars)
   {
      this->variable_list = vars;
   }

   virtual ~ir_array_splitting_visitor()
   {
   }

   virtual ir_visitor_status visit_leave(ir_assignment *);

   void split_deref(ir_dereference **deref);
   void handle_rvalue(ir_rvalue **rvalue);
   variable_entry *get_splitting_entry(ir_variable *var);

   exec_list *variable_list;
};

variable_entry *
ir_array_splitting_visitor::get_splitting_entry(ir_variable *var)
{
   assert(var);

   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      if (entry->var == var) {
	 return entry;
      }
   }

   return NULL;
}

void
ir_array_splitting_visitor::split_deref(ir_dereference **deref)
{
   ir_dereference_array *deref_array = (*deref)->as_dereference_array();
   if (!deref_array)
      return;

   ir_dereference_variable *deref_var = deref_array->array->as_dereference_variable();
   if (!deref_var)
      return;
   ir_variable *var = deref_var->var;

   variable_entry *entry = get_splitting_entry(var);
   if (!entry)
      return;

   ir_constant *constant = deref_array->array_index->as_constant();
   assert(constant);

   if (constant->value.i[0] < (int)entry->size) {
      *deref = new(entry->mem_ctx)
	 ir_dereference_variable(entry->components[constant->value.i[0]]);
   } else {
      /* There was a constant array access beyond the end of the
       * array.  This might have happened due to constant folding
       * after the initial parse.  This produces an undefined value,
       * but shouldn't crash.  Just give them an uninitialized
       * variable.
       */
      ir_variable *temp = new(entry->mem_ctx) ir_variable(deref_array->type,
							  "undef",
							  ir_var_temporary);
      entry->components[0]->insert_before(temp);
      *deref = new(entry->mem_ctx) ir_dereference_variable(temp);
   }
}

void
ir_array_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_dereference *deref = (*rvalue)->as_dereference();

   if (!deref)
      return;

   split_deref(&deref);
   *rvalue = deref;
}

ir_visitor_status
ir_array_splitting_visitor::visit_leave(ir_assignment *ir)
{
   /* The normal rvalue visitor skips the LHS of assignments, but we
    * need to process those just the same.
    */
   ir_rvalue *lhs = ir->lhs;

   handle_rvalue(&lhs);
   ir->lhs = lhs->as_dereference();

   ir->lhs->accept(this);

   handle_rvalue(&ir->rhs);
   ir->rhs->accept(this);

   if (ir->condition) {
      handle_rvalue(&ir->condition);
      ir->condition->accept(this);
   }

   return visit_continue;
}

bool
optimize_split_arrays(exec_list *instructions, bool linked)
{
   ir_array_reference_visitor refs;
   if (!refs.get_split_list(instructions, linked))
      return false;

   void *mem_ctx = ralloc_context(NULL);

   /* Replace the decls of the arrays to be split with their split
    * components.
    */
   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      const struct glsl_type *type = entry->var->type;
      const struct glsl_type *subtype;

      if (type->is_matrix())
	 subtype = type->column_type();
      else
	 subtype = type->fields.array;

      entry->mem_ctx = ralloc_parent(entry->var);

      entry->components = ralloc_array(mem_ctx,
				       ir_variable *,
				       entry->size);

      for (unsigned int i = 0; i < entry->size; i++) {
	 const char *name = ralloc_asprintf(mem_ctx, "%s_%d",
					    entry->var->name, i);

	 entry->components[i] =
	    new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary);
	 entry->var->insert_before(entry->components[i]);
      }

      entry->var->remove();
   }

   ir_array_splitting_visitor split(&refs.variable_list);
   visit_list_elements(&split, instructions);

   if (debug)
      _mesa_print_ir(instructions, NULL);

   ralloc_free(mem_ctx);

   return true;

}
<|endoftext|>