blob: d85243d5c06de54281add1eaaa51228fcd1a0633 [file] [log] [blame]
/*
* Copyright (C) 2015 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 android.support.constraint.solver;
import java.util.Arrays;
import static android.support.constraint.solver.LinearSystem.FULL_DEBUG;
/**
* Represents a given variable used in the {@link LinearSystem linear expression solver}.
*/
public class SolverVariable {
private static final boolean INTERNAL_DEBUG = FULL_DEBUG;
@SuppressWarnings("WeakerAccess")
public static final int STRENGTH_NONE = 0;
public static final int STRENGTH_LOW = 1;
public static final int STRENGTH_MEDIUM = 2;
public static final int STRENGTH_HIGH = 3;
@SuppressWarnings("WeakerAccess")
public static final int STRENGTH_HIGHEST = 4;
public static final int STRENGTH_EQUALITY = 5;
public static final int STRENGTH_FIXED = 6;
public static final int STRENGTH_BARRIER = 7;
private static int uniqueSlackId = 1;
private static int uniqueErrorId = 1;
private static int uniqueUnrestrictedId = 1;
private static int uniqueConstantId = 1;
private static int uniqueId = 1;
private String mName;
public int id = -1;
int definitionId = -1;
public int strength = 0;
public float computedValue;
final static int MAX_STRENGTH = 7;
float[] strengthVector = new float[MAX_STRENGTH];
Type mType;
ArrayRow[] mClientEquations = new ArrayRow[8];
int mClientEquationsCount = 0;
public int usageInRowCount = 0;
/**
* Type of variables
*/
public enum Type {
/**
* The variable can take negative or positive values
*/
UNRESTRICTED,
/**
* The variable is actually not a variable :) , but a constant number
*/
CONSTANT,
/**
* The variable is restricted to positive values and represents a slack
*/
SLACK,
/**
* The variable is restricted to positive values and represents an error
*/
ERROR,
/**
* Unknown (invalid) type.
*/
UNKNOWN
}
static void increaseErrorId() {
uniqueErrorId++;
}
private static String getUniqueName(Type type, String prefix) {
if (prefix != null) {
return prefix + uniqueErrorId;
}
switch (type) {
case UNRESTRICTED: return "U" + ++uniqueUnrestrictedId;
case CONSTANT: return "C" + ++uniqueConstantId;
case SLACK: return "S" + ++uniqueSlackId;
case ERROR: {
return "e" + ++uniqueErrorId;
}
case UNKNOWN:
return "V" + ++uniqueId;
}
throw new AssertionError(type.name());
}
/**
* Base constructor
* @param name the variable name
* @param type the type of the variable
*/
public SolverVariable(String name, Type type) {
mName = name;
mType = type;
}
public SolverVariable(Type type, String prefix) {
mType = type;
if (INTERNAL_DEBUG) {
//mName = getUniqueName(type, prefix);
}
}
void clearStrengths() {
for (int i = 0; i < MAX_STRENGTH; i++) {
strengthVector[i] = 0;
}
}
String strengthsToString() {
String representation = this + "[";
boolean negative = false;
boolean empty = true;
for (int j = 0; j < strengthVector.length; j++) {
representation += strengthVector[j];
if (strengthVector[j] > 0) {
negative = false;
} else if (strengthVector[j] < 0) {
negative = true;
}
if (strengthVector[j] != 0) {
empty = false;
}
if (j < strengthVector.length - 1) {
representation += ", ";
} else {
representation += "] ";
}
}
if (negative) {
representation += " (-)";
}
if (empty) {
representation += " (*)";
}
// representation += " {id: " + id + "}";
return representation;
}
public final void addToRow(ArrayRow row) {
for (int i = 0; i < mClientEquationsCount; i++) {
if (mClientEquations[i] == row) {
return;
}
}
if (mClientEquationsCount >= mClientEquations.length) {
mClientEquations = Arrays.copyOf(mClientEquations, mClientEquations.length * 2);
}
mClientEquations[mClientEquationsCount] = row;
mClientEquationsCount++;
}
public final void removeFromRow(ArrayRow row) {
final int count = mClientEquationsCount;
for (int i = 0; i < count; i++) {
if (mClientEquations[i] == row) {
for (int j = 0; j < (count - i - 1); j++) {
mClientEquations[i + j] = mClientEquations[i + j + 1];
}
mClientEquationsCount--;
return;
}
}
}
public final void updateReferencesWithNewDefinition(ArrayRow definition) {
final int count = mClientEquationsCount;
for (int i = 0; i < count; i++) {
mClientEquations[i].variables.updateFromRow(mClientEquations[i], definition, false);
}
mClientEquationsCount = 0;
}
public void reset() {
mName = null;
mType = Type.UNKNOWN;
strength = SolverVariable.STRENGTH_NONE;
id = -1;
definitionId = -1;
computedValue = 0;
mClientEquationsCount = 0;
usageInRowCount = 0;
}
/**
* Accessor for the name
*
* @return the name of the variable
*/
public String getName() {
return mName;
}
public void setName(String name) { mName = name; }
public void setType(Type type, String prefix) {
mType = type;
if (INTERNAL_DEBUG && mName == null) {
mName = getUniqueName(type, prefix);
}
}
/**
* Override the toString() method to display the variable
*/
@Override
public String toString() {
String result = "";
if (INTERNAL_DEBUG) {
result += mName + ":" + strength;
} else {
result += mName;
}
return result;
}
}