flutter/packages/cassowary/lib/expression.dart

116 lines
3.5 KiB
Dart

// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of cassowary;
class Expression extends EquationMember {
final List<Term> terms;
final double constant;
double get value => terms.fold(constant, (value, term) => value + term.value);
Expression(this.terms, this.constant);
Constraint _createConstraint(
EquationMember /* rhs */ value, Relation relation) {
if (value is ConstantMember) {
return new Constraint(new Expression(
new List.from(this.terms), this.constant - value.value), relation);
}
if (value is Variable) {
var newTerms = new List<Term>.from(this.terms)
..add(new Term(value, -1.0));
return new Constraint(new Expression(newTerms, this.constant), relation);
}
if (value is Term) {
var newTerms = new List<Term>.from(this.terms)
..add(new Term(value.variable, -value.coefficient));
return new Constraint(new Expression(newTerms, this.constant), relation);
}
if (value is Expression) {
var newTerms = value.terms.fold(new List<Term>.from(this.terms),
(list, t) => list..add(new Term(t.variable, -t.coefficient)));
return new Constraint(
new Expression(newTerms, this.constant - value.constant), relation);
}
assert(false);
return null;
}
Constraint operator >=(EquationMember value) =>
_createConstraint(value, Relation.greaterThanOrEqualTo);
Constraint operator <=(EquationMember value) =>
_createConstraint(value, Relation.lessThanOrEqualTo);
operator ==(EquationMember value) =>
_createConstraint(value, Relation.equalTo);
Expression operator +(EquationMember m) {
if (m is ConstantMember) {
return new Expression(new List.from(this.terms), this.constant + m.value);
}
if (m is Variable) {
return new Expression(
new List.from(this.terms)..add(new Term(m, 1.0)), this.constant);
}
if (m is Term) {
return new Expression(new List.from(this.terms)..add(m), this.constant);
}
if (m is Expression) {
return new Expression(new List.from(this.terms)..addAll(m.terms),
this.constant + m.constant);
}
assert(false);
return null;
}
Expression operator -(EquationMember m) {
if (m is ConstantMember) {
return new Expression(new List.from(this.terms), this.constant - m.value);
}
if (m is Variable) {
return new Expression(
new List.from(this.terms)..add(new Term(m, -1.0)), this.constant);
}
if (m is Term) {
return new Expression(new List.from(this.terms)
..add(new Term(m.variable, -m.coefficient)), this.constant);
}
if (m is Expression) {
var copiedTerms = new List<Term>.from(this.terms);
m.terms.forEach(
(t) => copiedTerms.add(new Term(t.variable, -t.coefficient)));
return new Expression(copiedTerms, this.constant - m.constant);
}
assert(false);
return null;
}
EquationMember operator *(double m) {
var terms = this.terms.fold(new List<Term>(), (list, term) => list
..add(new Term(term.variable, term.coefficient * m)));
return new Expression(terms, this.constant);
}
// TODO(csg): Figure out how to dry this up.
EquationMember operator /(double m) {
var terms = this.terms.fold(new List<Term>(), (list, term) => list
..add(new Term(term.variable, term.coefficient / m)));
return new Expression(terms, this.constant);
}
}