116 lines
3.5 KiB
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);
|
|
}
|
|
}
|