aboutsummaryrefslogtreecommitdiffstats
path: root/tests/benchmarks/qml/deltablue/Constraint.qml
blob: bf84870fa9e9ec8f72144e788b0516b476580e56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

pragma Strict
import QtQml

BaseConstraint {
    id: self

    property Variable myInput
    property Variable myOutput

    property Variable scale
    property Variable offset

    function addToGraph() {
        let ihn = myInput;
        if (ihn)
            ihn.addConstraint(self);
        let out = myOutput;
        if (out)
            out.addConstraint(self);
        let s = scale;
        if (s)
            s.addConstraint(self);
        let o = offset;
        if (o)
            o.addConstraint(self);
        satisfaction = Satisfaction.NONE;
    }

    function removeFromGraph() {
        if (myInput)
            myInput.removeConstraint(self);
        if (myOutput)
            myOutput.removeConstraint(self);
        if (scale)
            scale.removeConstraint(self);
        if (offset)
            offset.removeConstraint(self);
        satisfaction = Satisfaction.NONE;
    }

    property Variable input: (satisfaction === Satisfaction.BACKWARD)
        ? myOutput
        : myInput

    property Variable output: (satisfaction === Satisfaction.BACKWARD)
        ? myInput
        : myOutput

    function recalculate() {
        let ihn = input;
        let out = output;

        if (!ihn) {
            out.walkStrength = strength;
            out.stay = !isInput;
            return;
        }

        out.walkStrength = Strength.weakestOf(strength, ihn.walkStrength);
        let stay = ihn.stay;

        // Optimize for number of lookups. We lookup scale and offset only once and we keep
        // stay in a local as long as we can.

        let s = scale
        if (s)
            stay = stay && s.stay;

        let o = offset
        if (o)
            stay = stay && o.stay;

        out.stay = stay;

        if (stay)
            out.value = evaluate();
    }

    function chooseMethod(mark: int) {
        let ihn = myInput;
        let out = myOutput;
        let outStrength = out.walkStrength;

        if (!ihn) {
            satisfaction = (out.mark !== mark && Strength.stronger(strength, outStrength))
                ? Satisfaction.FORWARD
                : Satisfaction.NONE;
            return;
        }

        let ihnStrength = ihn.walkStrength;

        if (Strength.weaker(ihnStrength, outStrength)) {
            satisfaction = Strength.stronger(strength, ihnStrength)
                ? Satisfaction.BACKWARD
                : Satisfaction.NONE;
            return;
        }

        satisfaction = Strength.stronger(strength, outStrength)
            ? Satisfaction.FORWARD
            : Satisfaction.BACKWARD
    }

    function markInputs(mark: int) {
        let i = input;
        if (i)
            i.mark = mark;
        let s = scale;
        if (s)
            s.mark = mark;
        let o = offset;
        if (o)
            o.mark = mark;
    }

    function inputsKnown(mark: int) : bool {
        let ihn = input;
        return !ihn || ihn.mark === mark || ihn.stay || ihn.determinedBy === null;
    }

    function evaluate() : int {
        let result = input.value;

        // This is a rather hot code path. It pays off to do the lookups for offset and scale
        // only once
        let o = offset;
        let s = scale;

        if (satisfaction === Satisfaction.BACKWARD) {
            if (o)
                result = result - o.value;
            if (s)
                result = result / s.value;
        } else {
            if (s)
                result = result * s.value;
            if (o)
                result = result + o.value; // TODO: += and -= miscompile!
        }

        return result;
    }
}