public class

PriorityGoalRow

extends ArrayRow

 java.lang.Object

androidx.constraintlayout.core.ArrayRow

↳androidx.constraintlayout.core.PriorityGoalRow

Gradle dependencies

compile group: 'androidx.constraintlayout', name: 'constraintlayout-core', version: '1.1.0-beta01'

  • groupId: androidx.constraintlayout
  • artifactId: constraintlayout-core
  • version: 1.1.0-beta01

Artifact androidx.constraintlayout:constraintlayout-core:1.1.0-beta01 it located at Google repository (https://maven.google.com/)

Overview

Implements a row containing goals taking in account priorities.

Summary

Fields
from ArrayRowvariables
Constructors
publicPriorityGoalRow(Cache cache)

Methods
public voidaddError(SolverVariable error)

public voidclear()

public SolverVariablegetPivotCandidate(LinearSystem system, boolean[] avoid[])

public booleanisEmpty()

public java.lang.StringtoString()

public voidupdateFromRow(LinearSystem system, ArrayRow definition, boolean removeFromDefinition)

from ArrayRowaddError, createRowDimensionRatio, createRowEqualDimension, createRowEqualMatchDimensions, createRowEquals, createRowEquals, createRowGreaterThan, createRowGreaterThan, createRowLowerThan, createRowWithAngle, getKey, initFromRow, pickPivot, reset, updateFromFinalVariable, updateFromSynonymVariable, updateFromSystem
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Constructors

public PriorityGoalRow(Cache cache)

Methods

public void clear()

public boolean isEmpty()

public SolverVariable getPivotCandidate(LinearSystem system, boolean[] avoid[])

public void addError(SolverVariable error)

public void updateFromRow(LinearSystem system, ArrayRow definition, boolean removeFromDefinition)

public java.lang.String toString()

Source

/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.constraintlayout.core;

import java.util.Arrays;
import java.util.Comparator;

/**
 * Implements a row containing goals taking in account priorities.
 */
public class PriorityGoalRow extends ArrayRow {
    private static final float EPSILON = 0.0001f;
    @SuppressWarnings("unused") private static final boolean DEBUG = false;

    private int mTableSize = 128;
    private SolverVariable[] mArrayGoals = new SolverVariable[mTableSize];
    private SolverVariable[] mSortArray = new SolverVariable[mTableSize];
    private int mNumGoals = 0;
    GoalVariableAccessor mAccessor = new GoalVariableAccessor(this);

    class GoalVariableAccessor {
        SolverVariable mVariable;
        PriorityGoalRow mRow;

        GoalVariableAccessor(PriorityGoalRow row) {
            this.mRow = row;
        }

        public void init(SolverVariable variable) {
            this.mVariable = variable;
        }

        public boolean addToGoal(SolverVariable other, float value) {
            if (mVariable.inGoal) {
                boolean empty = true;
                for (int i = 0; i < SolverVariable.MAX_STRENGTH; i++) {
                    mVariable.mGoalStrengthVector[i] += other.mGoalStrengthVector[i] * value;
                    float v = mVariable.mGoalStrengthVector[i];
                    if (Math.abs(v) < EPSILON) {
                        mVariable.mGoalStrengthVector[i] = 0;
                    } else {
                        empty = false;
                    }
                }
                if (empty) {
                    removeGoal(mVariable);
                }
            } else {
                for (int i = 0; i < SolverVariable.MAX_STRENGTH; i++) {
                    float strength = other.mGoalStrengthVector[i];
                    if (strength != 0) {
                        float v = value * strength;
                        if (Math.abs(v) < EPSILON) {
                            v = 0;
                        }
                        mVariable.mGoalStrengthVector[i] = v;
                    } else {
                        mVariable.mGoalStrengthVector[i] = 0;
                    }
                }
                return true;
            }
            return false;
        }

        public void add(SolverVariable other) {
            for (int i = 0; i < SolverVariable.MAX_STRENGTH; i++) {
                mVariable.mGoalStrengthVector[i] += other.mGoalStrengthVector[i];
                float value = mVariable.mGoalStrengthVector[i];
                if (Math.abs(value) < EPSILON) {
                    mVariable.mGoalStrengthVector[i] = 0;
                }
            }
        }

        public final boolean isNegative() {
            for (int i = SolverVariable.MAX_STRENGTH - 1; i >= 0; i--) {
                float value = mVariable.mGoalStrengthVector[i];
                if (value > 0) {
                    return false;
                }
                if (value < 0) {
                    return true;
                }
            }
            return false;
        }

        public final boolean isSmallerThan(SolverVariable other) {
            for (int i = SolverVariable.MAX_STRENGTH - 1; i >= 0; i--) {
                float comparedValue = other.mGoalStrengthVector[i];
                float value = mVariable.mGoalStrengthVector[i];
                if (value == comparedValue) {
                    continue;
                }
                return value < comparedValue;
            }
            return false;
        }

        public final boolean isNull() {
            for (int i = 0; i < SolverVariable.MAX_STRENGTH; i++) {
                if (mVariable.mGoalStrengthVector[i] != 0) {
                    return false;
                }
            }
            return true;
        }

        public void reset() {
            Arrays.fill(mVariable.mGoalStrengthVector, 0);
        }

        @Override
        public String toString() {
            String result = "[ ";
            if (mVariable != null) {
                for (int i = 0; i < SolverVariable.MAX_STRENGTH; i++) {
                    result += mVariable.mGoalStrengthVector[i] + " ";
                }
            }
            result += "] " + mVariable;
            return result;
        }

    }

    @Override
    public void clear() {
        mNumGoals = 0;
        mConstantValue = 0;
    }

    Cache mCache;

    public PriorityGoalRow(Cache cache) {
        super(cache);
        mCache = cache;
    }

    @Override
    public boolean isEmpty() {
        return mNumGoals == 0;
    }

    static final int NOT_FOUND = -1;

    @Override
    public SolverVariable getPivotCandidate(LinearSystem system, boolean[] avoid) {
        int pivot = NOT_FOUND;
        for (int i = 0; i < mNumGoals; i++) {
            SolverVariable variable = mArrayGoals[i];
            if (avoid[variable.id]) {
                continue;
            }
            mAccessor.init(variable);
            if (pivot == NOT_FOUND) {
                if (mAccessor.isNegative()) {
                    pivot = i;
                }
            } else if (mAccessor.isSmallerThan(mArrayGoals[pivot])) {
                pivot = i;
            }
        }
        if (pivot == NOT_FOUND) {
            return null;
        }
        return mArrayGoals[pivot];
    }

    @Override
    public void addError(SolverVariable error) {
        mAccessor.init(error);
        mAccessor.reset();
        error.mGoalStrengthVector[error.strength] = 1;
        addToGoal(error);
    }

    private void addToGoal(SolverVariable variable) {
        if (mNumGoals + 1 > mArrayGoals.length) {
            mArrayGoals = Arrays.copyOf(mArrayGoals, mArrayGoals.length * 2);
            mSortArray = Arrays.copyOf(mArrayGoals, mArrayGoals.length * 2);
        }
        mArrayGoals[mNumGoals] = variable;
        mNumGoals++;

        if (mNumGoals > 1 && mArrayGoals[mNumGoals - 1].id > variable.id) {
            for (int i = 0; i < mNumGoals; i++) {
                mSortArray[i] = mArrayGoals[i];
            }
            Arrays.sort(mSortArray, 0, mNumGoals, new Comparator<SolverVariable>() {
                @Override
                public int compare(SolverVariable variable1, SolverVariable variable2) {
                    return variable1.id - variable2.id;
                }
            });
            for (int i = 0; i < mNumGoals; i++) {
                mArrayGoals[i] = mSortArray[i];
            }
        }

        variable.inGoal = true;
        variable.addToRow(this);
    }

    private void removeGoal(SolverVariable variable) {
        for (int i = 0; i < mNumGoals; i++) {
            if (mArrayGoals[i] == variable) {
                for (int j = i; j < mNumGoals - 1; j++) {
                    mArrayGoals[j] = mArrayGoals[j + 1];
                }
                mNumGoals--;
                variable.inGoal = false;
                return;
            }
        }
    }

    @Override
    public void updateFromRow(LinearSystem system,
            ArrayRow definition,
            boolean removeFromDefinition) {
        SolverVariable goalVariable = definition.mVariable;
        if (goalVariable == null) {
            return;
        }

        ArrayRowVariables rowVariables = definition.variables;
        int currentSize = rowVariables.getCurrentSize();
        for (int i = 0; i < currentSize; i++) {
            SolverVariable solverVariable = rowVariables.getVariable(i);
            float value = rowVariables.getVariableValue(i);
            mAccessor.init(solverVariable);
            if (mAccessor.addToGoal(goalVariable, value)) {
                addToGoal(solverVariable);
            }
            mConstantValue += definition.mConstantValue * value;
        }
        removeGoal(goalVariable);
    }

    @Override
    public String toString() {
        String result = "";
        result += " goal -> (" + mConstantValue + ") : ";
        for (int i = 0; i < mNumGoals; i++) {
            SolverVariable v = mArrayGoals[i];
            mAccessor.init(v);
            result += mAccessor + " ";
        }
        return result;
    }
}