1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2 // Licensed under the MIT License:
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21
22 #include "null-common.h"
23
24 namespace capnp {
25 namespace benchmark {
26 namespace null {
27
28 enum class Operation {
29 ADD,
30 SUBTRACT,
31 MULTIPLY,
32 DIVIDE,
33 MODULUS
34 };
35 uint OPERATION_RANGE = static_cast<uint>(Operation::MODULUS) + 1;
36
37 struct Expression {
38 Operation op;
39
40 bool leftIsValue;
41 bool rightIsValue;
42
43 union {
44 int32_t leftValue;
45 Expression* leftExpression;
46 };
47
48 union {
49 int32_t rightValue;
50 Expression* rightExpression;
51 };
52 };
53
makeExpression(Expression * exp,uint depth)54 int32_t makeExpression(Expression* exp, uint depth) {
55 exp->op = (Operation)(fastRand(OPERATION_RANGE));
56
57 int32_t left, right;
58
59 if (fastRand(8) < depth) {
60 exp->leftIsValue = true;
61 left = fastRand(128) + 1;
62 exp->leftValue = left;
63 } else {
64 exp->leftIsValue = false;
65 exp->leftExpression = allocate<Expression>();
66 left = makeExpression(exp->leftExpression, depth + 1);
67 }
68
69 if (fastRand(8) < depth) {
70 exp->rightIsValue = true;
71 right = fastRand(128) + 1;
72 exp->rightValue = right;
73 } else {
74 exp->rightIsValue = false;
75 exp->rightExpression = allocate<Expression>();
76 right = makeExpression(exp->rightExpression, depth + 1);
77 }
78
79 switch (exp->op) {
80 case Operation::ADD:
81 return left + right;
82 case Operation::SUBTRACT:
83 return left - right;
84 case Operation::MULTIPLY:
85 return left * right;
86 case Operation::DIVIDE:
87 return div(left, right);
88 case Operation::MODULUS:
89 return mod(left, right);
90 }
91 throw std::logic_error("Can't get here.");
92 }
93
evaluateExpression(const Expression & exp)94 int32_t evaluateExpression(const Expression& exp) {
95 uint32_t left, right;
96
97 if (exp.leftIsValue) {
98 left = exp.leftValue;
99 } else {
100 left = evaluateExpression(*exp.leftExpression);
101 }
102
103 if (exp.rightIsValue) {
104 right = exp.rightValue;
105 } else {
106 right = evaluateExpression(*exp.rightExpression);
107 }
108
109 switch (exp.op) {
110 case Operation::ADD:
111 return left + right;
112 case Operation::SUBTRACT:
113 return left - right;
114 case Operation::MULTIPLY:
115 return left * right;
116 case Operation::DIVIDE:
117 return div(left, right);
118 case Operation::MODULUS:
119 return mod(left, right);
120 }
121 throw std::logic_error("Can't get here.");
122 }
123
124 class ExpressionTestCase {
125 public:
126 typedef Expression Request;
127 typedef int32_t Response;
128 typedef int32_t Expectation;
129
setupRequest(Expression * request)130 static inline int32_t setupRequest(Expression* request) {
131 return makeExpression(request, 0);
132 }
handleRequest(const Expression & request,int32_t * response)133 static inline void handleRequest(const Expression& request, int32_t* response) {
134 *response = evaluateExpression(request);
135 }
checkResponse(int32_t response,int32_t expected)136 static inline bool checkResponse(int32_t response, int32_t expected) {
137 return response == expected;
138 }
139
spaceUsed(const Expression & expression)140 static size_t spaceUsed(const Expression& expression) {
141 return sizeof(Expression) +
142 (expression.leftExpression == nullptr ? 0 : spaceUsed(*expression.leftExpression)) +
143 (expression.rightExpression == nullptr ? 0 : spaceUsed(*expression.rightExpression));
144 }
145 };
146
147 } // namespace null
148 } // namespace benchmark
149 } // namespace capnp
150
main(int argc,char * argv[])151 int main(int argc, char* argv[]) {
152 return capnp::benchmark::benchmarkMain<
153 capnp::benchmark::null::BenchmarkTypes,
154 capnp::benchmark::null::ExpressionTestCase>(argc, argv);
155 }
156