souffle  2.0.2-371-g6315b36
ram_arithmetic_test.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2020, The Souffle Developers. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file ram_arithmetic_test.cpp
12  *
13  * Tests arithmetic evaluation by the Interpreter.
14  *
15  ***********************************************************************/
16 
17 #include "tests/test.h"
18 
19 #include "FunctorOps.h"
20 #include "Global.h"
21 #include "interpreter/Engine.h"
22 #include "ram/Expression.h"
23 #include "ram/IntrinsicOperator.h"
24 #include "ram/Program.h"
25 #include "ram/Query.h"
26 #include "ram/Relation.h"
27 #include "ram/Sequence.h"
28 #include "ram/SignedConstant.h"
29 #include "ram/Statement.h"
30 #include "ram/SubroutineReturn.h"
31 #include "ram/TranslationUnit.h"
32 #include "reports/DebugReport.h"
33 #include "reports/ErrorReport.h"
34 #include "souffle/RamTypes.h"
35 #include "souffle/SymbolTable.h"
36 #include <algorithm>
37 #include <cmath>
38 #include <cstddef>
39 #include <map>
40 #include <memory>
41 #include <string>
42 #include <type_traits>
43 #include <utility>
44 #include <vector>
45 
47 
48 using namespace ram;
49 
50 #define TESTS_PER_OPERATION 20
51 
52 /** Function to evaluate a single Expression. */
53 RamDomain evalExpression(Own<Expression> expression, SymbolTable& symTab) {
54  // Set up Program and translation unit
55  VecOwn<Expression> returnValues;
56  returnValues.emplace_back(std::move(expression));
57 
58  Global::config().set("jobs", "1");
59  Own<Statement> query = mk<ram::Query>(mk<ram::SubroutineReturn>(std::move(returnValues)));
60  std::map<std::string, Own<Statement>> subs;
61  subs.insert(std::make_pair("test", std::move(query)));
63 
64  Own<Program> prog = mk<Program>(std::move(rels), mk<ram::Sequence>(), std::move(subs));
65 
66  ErrorReport errReport;
67  DebugReport debugReport;
68 
69  TranslationUnit translationUnit(std::move(prog), symTab, errReport, debugReport);
70 
71  // configure and execute interpreter
72  Own<Engine> interpreter = mk<Engine>(translationUnit);
73 
74  std::string name("test");
75  std::vector<RamDomain> ret;
76 
77  interpreter->executeSubroutine(name, {}, ret);
78 
79  return ret.at(0);
80 }
81 
82 /** Function to evaluate a single Expression. */
84  SymbolTable symTab;
85  return evalExpression(std::move(expression), symTab);
86 }
87 
88 RamDomain evalMultiArg(FunctorOp functor, VecOwn<Expression> args, SymbolTable& symTab) {
89  return evalExpression(mk<ram::IntrinsicOperator>(functor, std::move(args)), symTab);
90 }
91 
93  SymbolTable symTab;
94  return evalMultiArg(functor, std::move(args), symTab);
95 }
96 
97 /** Evaluate a single argument expression */
99  VecOwn<Expression> args;
100  args.push_back(mk<SignedConstant>(arg1));
101 
102  return evalMultiArg(functor, std::move(args));
103 }
104 
105 /** Evaluate a binary operator */
106 RamDomain evalBinary(FunctorOp functor, RamDomain arg1, RamDomain arg2) {
107  VecOwn<Expression> args;
108  args.push_back(mk<SignedConstant>(arg1));
109  args.push_back(mk<SignedConstant>(arg2));
110 
111  return evalMultiArg(functor, std::move(args));
112 }
113 
114 TEST(SignedConstant, ArithmeticEvaluation) {
115  RamDomain num = 42;
116  Own<Expression> expression = mk<SignedConstant>(num);
117  RamDomain result = evalExpression(std::move(expression));
118  EXPECT_EQ(result, num);
119 }
120 
121 TEST(Unary, Neg) {
122  for (RamDomain randomNumber : testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION)) {
123  EXPECT_EQ(evalUnary(FunctorOp::NEG, randomNumber), -randomNumber);
124  }
125 }
126 
127 TEST(Unary, FloatNeg) {
128  FunctorOp functor = FunctorOp::FNEG;
129 
130  for (auto randomNumber : testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION)) {
131  auto result = evalUnary(functor, ramBitCast(randomNumber));
132  EXPECT_EQ(ramBitCast<RamFloat>(result), -randomNumber);
133  }
134 }
135 
136 TEST(Unary, BinaryNot) {
137  FunctorOp functor = FunctorOp::BNOT;
138 
139  for (auto randomNumber : testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION)) {
140  EXPECT_EQ(evalUnary(functor, randomNumber), ~randomNumber);
141  }
142 }
143 
144 TEST(Unary, UnsignedBinaryNot) {
145  FunctorOp functor = FunctorOp::UBNOT;
146 
147  for (auto randomNumber : testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION)) {
148  RamDomain result = evalUnary(functor, ramBitCast(randomNumber));
149  EXPECT_EQ(ramBitCast<RamUnsigned>(result), ~randomNumber);
150  }
151 }
152 
153 TEST(Unary, LogicalNeg) {
154  FunctorOp functor = FunctorOp::LNOT;
155 
156  for (auto randomNumber : testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION)) {
157  EXPECT_EQ(evalUnary(functor, randomNumber), !randomNumber);
158  }
159 }
160 
161 TEST(Unary, UnsignedLogicalNeg) {
162  FunctorOp functor = FunctorOp::ULNOT;
163 
164  for (auto randomNumber : testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION)) {
165  RamDomain result = evalUnary(functor, ramBitCast(randomNumber));
166  EXPECT_EQ(ramBitCast<RamUnsigned>(result), static_cast<RamUnsigned>(!randomNumber));
167  }
168 }
169 
170 TEST(Unary, SingedTpUnsigned) {
171  FunctorOp functor = FunctorOp::I2U;
172 
173  for (auto randomNumber : testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION)) {
174  RamDomain result = evalUnary(functor, randomNumber);
175  EXPECT_EQ(ramBitCast<RamUnsigned>(result), static_cast<RamUnsigned>(randomNumber));
176  }
177 }
178 
179 TEST(Unary, UnsignedToSigned) {
180  FunctorOp functor = FunctorOp::U2I;
181 
182  for (auto randomNumber : testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION)) {
183  RamDomain result = evalUnary(functor, ramBitCast(randomNumber));
184  EXPECT_EQ(result, static_cast<RamDomain>(randomNumber));
185  }
186 }
187 
188 TEST(Unary, SignedToFloat) {
189  FunctorOp functor = FunctorOp::I2F;
190 
191  for (auto randomNumber : testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION)) {
192  RamDomain result = evalUnary(functor, ramBitCast(randomNumber));
193  EXPECT_EQ(ramBitCast<RamFloat>(result), static_cast<RamFloat>(randomNumber));
194  }
195 }
196 
197 TEST(Unary, FloatToSigned) {
198  FunctorOp functor = FunctorOp::F2I;
199 
200  for (auto randomNumber : testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION)) {
201  RamDomain result = evalUnary(functor, ramBitCast(randomNumber));
202  EXPECT_EQ(result, static_cast<RamDomain>(randomNumber));
203  }
204 }
205 
206 TEST(Unary, UnsignedToFloat) {
207  FunctorOp functor = FunctorOp::U2F;
208 
209  for (auto randomNumber : testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION)) {
210  RamDomain result = evalUnary(functor, ramBitCast(randomNumber));
211  EXPECT_EQ(ramBitCast<RamFloat>(result), static_cast<RamFloat>(randomNumber));
212  }
213 }
214 
215 TEST(Unary, FloatToUnsigned) {
216  FunctorOp functor = FunctorOp::F2U;
217 
218  for (auto randomNumber : testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION)) {
219  RamDomain result = evalUnary(functor, ramBitCast(randomNumber));
220  EXPECT_EQ(ramBitCast<RamUnsigned>(result), static_cast<RamUnsigned>(randomNumber));
221  }
222 }
223 
224 TEST(Binary, SignedAdd) {
225  FunctorOp functor = FunctorOp::ADD;
226 
227  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
228  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
229 
230  for (size_t i = 0; i < TESTS_PER_OPERATION; ++i) {
231  RamDomain arg1 = vecArg1[i];
232  RamDomain arg2 = vecArg2[i];
233  RamDomain result = evalBinary(functor, arg1, arg2);
234  EXPECT_EQ(result, arg1 + arg2);
235  }
236 }
237 
238 TEST(Binary, UnsignedAdd) {
239  FunctorOp functor = FunctorOp::UADD;
240 
241  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
242  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
243 
244  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
245  RamUnsigned arg1 = vecArg1[i];
246  RamUnsigned arg2 = vecArg2[i];
247  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
248  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 + arg2);
249  }
250 }
251 
252 TEST(Binary, FloatAdd) {
253  FunctorOp functor = FunctorOp::FADD;
254 
255  auto vecArg1 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
256  auto vecArg2 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
257 
258  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
259  auto arg1 = vecArg1[i];
260  auto arg2 = vecArg2[i];
261  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
262  EXPECT_EQ(ramBitCast<RamFloat>(result), arg1 + arg2);
263  }
264 }
265 
266 TEST(Binary, SignedSub) {
267  FunctorOp functor = FunctorOp::SUB;
268 
269  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
270  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
271 
272  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
273  auto arg1 = vecArg1[i];
274  auto arg2 = vecArg2[i];
275  RamDomain result = evalBinary(functor, arg1, arg2);
276  EXPECT_EQ(result, arg1 - arg2);
277  }
278 }
279 
280 TEST(Binary, UnsignedSub) {
281  FunctorOp functor = FunctorOp::USUB;
282 
283  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
284  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
285 
286  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
287  auto arg1 = vecArg1[i];
288  auto arg2 = vecArg2[i];
289  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
290  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 - arg2);
291  }
292 }
293 
294 TEST(Binary, FloatSub) {
295  FunctorOp functor = FunctorOp::FSUB;
296 
297  auto vecArg1 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
298  auto vecArg2 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
299 
300  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
301  auto arg1 = vecArg1[i];
302  auto arg2 = vecArg2[i];
303  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
304  EXPECT_EQ(ramBitCast<RamFloat>(result), arg1 - arg2);
305  }
306 }
307 
308 TEST(Binary, SignedMul) {
309  FunctorOp functor = FunctorOp::MUL;
310 
311  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
312  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
313 
314  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
315  auto arg1 = vecArg1[i];
316  auto arg2 = vecArg2[i];
317  RamDomain result = evalBinary(functor, arg1, arg2);
318  EXPECT_EQ(result, arg1 * arg2);
319  }
320 }
321 
322 TEST(Binary, UnsignedMul) {
323  FunctorOp functor = FunctorOp::UMUL;
324 
325  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
326  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
327 
328  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
329  auto arg1 = vecArg1[i];
330  auto arg2 = vecArg2[i];
331  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
332  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 * arg2);
333  }
334 }
335 
336 TEST(Binary, FloatMul) {
337  FunctorOp functor = FunctorOp::FMUL;
338 
339  auto vecArg1 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
340  auto vecArg2 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
341 
342  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
343  auto arg1 = vecArg1[i];
344  auto arg2 = vecArg2[i];
345  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
346  EXPECT_EQ(ramBitCast<RamFloat>(result), arg1 * arg2);
347  }
348 }
349 
350 TEST(Binary, SignedDiv) {
351  FunctorOp functor = FunctorOp::DIV;
352 
353  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
354  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
355 
356  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
357  auto arg1 = vecArg1[i];
358  auto arg2 = vecArg2[i];
359  if (arg2 != 0) {
360  RamDomain result = evalBinary(functor, arg1, arg2);
361  EXPECT_EQ(result, arg1 / arg2);
362  }
363  }
364 }
365 
366 TEST(Binary, UnsignedDiv) {
367  FunctorOp functor = FunctorOp::UDIV;
368 
369  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
370  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
371 
372  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
373  auto arg1 = vecArg1[i];
374  auto arg2 = vecArg2[i];
375  if (arg2 != 0) {
376  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
377  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 / arg2);
378  }
379  }
380 }
381 
382 TEST(Binary, FloatDiv) {
383  FunctorOp functor = FunctorOp::FDIV;
384 
385  auto vecArg1 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
386  auto vecArg2 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
387 
388  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
389  auto arg1 = vecArg1[i];
390  auto arg2 = vecArg2[i];
391  if (arg2 != 0) {
392  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
393  EXPECT_EQ(ramBitCast<RamFloat>(result), arg1 / arg2);
394  }
395  }
396 }
397 
398 TEST(Binary, SignedExp) {
399  FunctorOp functor = FunctorOp::EXP;
400 
401  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
402  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
403 
404  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
405  auto arg1 = vecArg1[i];
406  auto arg2 = vecArg2[i];
407  RamDomain result = evalBinary(functor, arg1, arg2);
408  EXPECT_EQ(result, static_cast<RamDomain>(std::pow(arg1, arg2)));
409  }
410 }
411 
412 TEST(Binary, UnsignedExp) {
413  FunctorOp functor = FunctorOp::UEXP;
414 
415  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
416  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
417 
418  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
419  auto arg1 = vecArg1[i];
420  auto arg2 = vecArg2[i];
421  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
422  EXPECT_EQ(ramBitCast<RamUnsigned>(result), static_cast<RamUnsigned>(std::pow(arg1, arg2)));
423  }
424 }
425 
426 TEST(Binary, FloatExp) {
427  FunctorOp functor = FunctorOp::FEXP;
428 
429  auto vecArg1 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
430  auto vecArg2 = testutil::generateRandomVector<RamFloat>(TESTS_PER_OPERATION);
431 
432  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
433  auto arg1 = vecArg1[i];
434  auto arg2 = vecArg2[i];
435  auto result = ramBitCast<RamFloat>(evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2)));
436  auto expected = static_cast<RamFloat>(std::pow(arg1, arg2));
437  EXPECT_TRUE((std::isnan(result) && std::isnan(expected)) || result == expected);
438  }
439 }
440 
441 TEST(Binary, SignedMod) {
442  FunctorOp functor = FunctorOp::MOD;
443 
444  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
445  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
446 
447  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
448  auto arg1 = vecArg1[i];
449  auto arg2 = vecArg2[i];
450  RamDomain result = evalBinary(functor, arg1, arg2);
451  EXPECT_EQ(result, arg1 % arg2);
452  }
453 }
454 
455 TEST(Binary, UnsignedMod) {
456  FunctorOp functor = FunctorOp::UMOD;
457 
458  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
459  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
460 
461  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
462  auto arg1 = vecArg1[i];
463  auto arg2 = vecArg2[i];
464  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
465  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 % arg2);
466  }
467 }
468 
469 TEST(Binary, SignedBinaryAnd) {
470  FunctorOp functor = FunctorOp::BAND;
471 
472  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
473  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
474 
475  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
476  auto arg1 = vecArg1[i];
477  auto arg2 = vecArg2[i];
478  RamDomain result = evalBinary(functor, arg1, arg2);
479  EXPECT_EQ(result, arg1 & arg2);
480  }
481 }
482 
483 TEST(Binary, UnsignedBinaryAnd) {
484  FunctorOp functor = FunctorOp::UBAND;
485 
486  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
487  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
488 
489  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
490  auto arg1 = vecArg1[i];
491  auto arg2 = vecArg2[i];
492  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
493  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 & arg2);
494  }
495 }
496 
497 TEST(Binary, SignedBinaryOr) {
498  FunctorOp functor = FunctorOp::BOR;
499 
500  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
501  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
502 
503  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
504  auto arg1 = vecArg1[i];
505  auto arg2 = vecArg2[i];
506  RamDomain result = evalBinary(functor, arg1, arg2);
507  EXPECT_EQ(result, arg1 | arg2);
508  }
509 }
510 
511 TEST(Binary, UnsignedBinaryOr) {
512  FunctorOp functor = FunctorOp::UBOR;
513 
514  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
515  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
516 
517  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
518  auto arg1 = vecArg1[i];
519  auto arg2 = vecArg2[i];
520  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
521  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 | arg2);
522  }
523 }
524 
525 TEST(Binary, SignedBinaryXor) {
526  FunctorOp functor = FunctorOp::BXOR;
527 
528  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
529  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
530 
531  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
532  auto arg1 = vecArg1[i];
533  auto arg2 = vecArg2[i];
534  RamDomain result = evalBinary(functor, arg1, arg2);
535  EXPECT_EQ(result, arg1 ^ arg2);
536  }
537 }
538 
539 TEST(Binary, UnsignedBinaryXor) {
540  FunctorOp functor = FunctorOp::UBXOR;
541 
542  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
543  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
544 
545  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
546  auto arg1 = vecArg1[i];
547  auto arg2 = vecArg2[i];
548  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
549  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 ^ arg2);
550  }
551 }
552 
553 TEST(Binary, SignedLogicalAnd) {
554  FunctorOp functor = FunctorOp::LAND;
555 
556  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
557  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
558 
559  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
560  auto arg1 = vecArg1[i];
561  auto arg2 = vecArg2[i];
562  RamDomain result = evalBinary(functor, arg1, arg2);
563  EXPECT_EQ(result, arg1 || arg2);
564  }
565 }
566 
567 TEST(Binary, UnsignedLogicalAnd) {
568  FunctorOp functor = FunctorOp::ULAND;
569 
570  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
571  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
572 
573  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
574  auto arg1 = vecArg1[i];
575  auto arg2 = vecArg2[i];
576  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
577  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 || arg2);
578  }
579 }
580 
581 TEST(Binary, SignedLogicalOr) {
582  FunctorOp functor = FunctorOp::LOR;
583 
584  auto vecArg1 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
585  auto vecArg2 = testutil::generateRandomVector<RamDomain>(TESTS_PER_OPERATION);
586 
587  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
588  auto arg1 = vecArg1[i];
589  auto arg2 = vecArg2[i];
590  RamDomain result = evalBinary(functor, arg1, arg2);
591  EXPECT_EQ(result, arg1 || arg2);
592  }
593 }
594 
595 TEST(Binary, UnsignedLogicalOr) {
596  FunctorOp functor = FunctorOp::ULOR;
597 
598  auto vecArg1 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
599  auto vecArg2 = testutil::generateRandomVector<RamUnsigned>(TESTS_PER_OPERATION);
600 
601  for (int i = 0; i < TESTS_PER_OPERATION; ++i) {
602  auto arg1 = vecArg1[i];
603  auto arg2 = vecArg2[i];
604  RamDomain result = evalBinary(functor, ramBitCast(arg1), ramBitCast(arg2));
605  EXPECT_EQ(ramBitCast<RamUnsigned>(result), arg1 || arg2);
606  }
607 }
608 
609 TEST(MultiArg, Max) {
610  FunctorOp functor = FunctorOp::MAX;
611  VecOwn<Expression> args;
612 
613  for (RamDomain i = 0; i <= 50; ++i) {
614  args.push_back(mk<SignedConstant>(i));
615  }
616 
617  RamDomain result = evalMultiArg(functor, std::move(args));
618 
619  EXPECT_EQ(result, 50);
620 }
621 
622 TEST(MultiArg, UnsignedMax) {
623  FunctorOp functor = FunctorOp::UMAX;
624  VecOwn<Expression> args;
625 
626  for (RamUnsigned i = 0; i <= 100; ++i) {
627  args.push_back(mk<SignedConstant>(ramBitCast(i)));
628  }
629 
630  RamDomain result = evalMultiArg(functor, std::move(args));
631 
632  EXPECT_EQ(ramBitCast<RamUnsigned>(result), 100);
633 }
634 
635 TEST(MultiArg, FloatMax) {
636  FunctorOp functor = FunctorOp::FMAX;
637  VecOwn<Expression> args;
638 
639  for (RamDomain i = -100; i <= 100; ++i) {
640  args.push_back(mk<SignedConstant>(ramBitCast(static_cast<RamFloat>(i))));
641  }
642 
643  RamDomain result = evalMultiArg(functor, std::move(args));
644 
645  EXPECT_EQ(ramBitCast<RamFloat>(result), static_cast<RamFloat>(100));
646 }
647 
648 TEST(MultiArg, SymbolMax) {
649  FunctorOp functor = FunctorOp::SMAX;
650  VecOwn<Expression> args;
651 
652  SymbolTable symTab;
653 
654  for (RamDomain i = -100; i <= 100; ++i) {
655  args.push_back(mk<SignedConstant>(symTab.lookup(std::to_string(i))));
656  }
657 
658  auto&& result = symTab.resolve(evalMultiArg(functor, std::move(args), symTab));
659 
660  EXPECT_EQ(result, "99");
661 }
662 
663 TEST(MultiArg, Min) {
664  FunctorOp functor = FunctorOp::MIN;
665  VecOwn<Expression> args;
666 
667  for (RamDomain i = 0; i <= 50; ++i) {
668  args.push_back(mk<SignedConstant>(i));
669  }
670 
671  RamDomain result = evalMultiArg(functor, std::move(args));
672 
673  EXPECT_EQ(result, 0);
674 }
675 
676 TEST(MultiArg, UnsignedMin) {
677  FunctorOp functor = FunctorOp::UMIN;
678  VecOwn<Expression> args;
679 
680  for (RamUnsigned i = 0; i <= 100; ++i) {
681  args.push_back(mk<SignedConstant>(ramBitCast(i)));
682  }
683 
684  RamDomain result = evalMultiArg(functor, std::move(args));
685 
686  EXPECT_EQ(ramBitCast<RamUnsigned>(result), 0);
687 }
688 
689 TEST(MultiArg, FloatMin) {
690  FunctorOp functor = FunctorOp::FMIN;
691  VecOwn<Expression> args;
692 
693  for (RamDomain i = -100; i <= 100; ++i) {
694  args.push_back(mk<SignedConstant>(ramBitCast(static_cast<RamFloat>(i))));
695  }
696 
697  RamDomain result = evalMultiArg(functor, std::move(args));
698 
699  EXPECT_EQ(ramBitCast<RamFloat>(result), static_cast<RamFloat>(-100));
700 }
701 
702 TEST(MultiArg, SymbolMin) {
703  FunctorOp functor = FunctorOp::SMIN;
704  VecOwn<Expression> args;
705 
706  SymbolTable symTab;
707 
708  for (RamDomain i = -100; i <= 100; ++i) {
709  args.push_back(mk<SignedConstant>(symTab.lookup(std::to_string(i))));
710  }
711 
712  auto&& result = symTab.resolve(evalMultiArg(functor, std::move(args), symTab));
713 
714  EXPECT_EQ(result, "-1");
715 }
716 
717 } // namespace souffle::interpreter::test
souffle::FunctorOp::DIV
@ DIV
souffle::FunctorOp::UEXP
@ UEXP
souffle::RamUnsigned
uint32_t RamUnsigned
Definition: RamTypes.h:58
souffle::FunctorOp::UBOR
@ UBOR
souffle::FunctorOp::U2I
@ U2I
souffle::FunctorOp::FDIV
@ FDIV
EXPECT_TRUE
#define EXPECT_TRUE(a)
Definition: test.h:189
souffle::FunctorOp::UBXOR
@ UBXOR
souffle::interpreter::test::evalMultiArg
RamDomain evalMultiArg(FunctorOp functor, VecOwn< Expression > args, SymbolTable &symTab)
Definition: ram_arithmetic_test.cpp:94
souffle::FunctorOp::FMIN
@ FMIN
souffle::SymbolTable::resolve
const std::string & resolve(const RamDomain index) const
Find a symbol in the table by its index, note that this gives an error if the index is out of bounds.
Definition: SymbolTable.h:154
DebugReport.h
souffle::FunctorOp::FADD
@ FADD
souffle::RamDomain
int32_t RamDomain
Definition: RamTypes.h:56
souffle::FunctorOp::FMUL
@ FMUL
souffle::FunctorOp::USUB
@ USUB
SymbolTable.h
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: test.h:191
souffle::FunctorOp::ULAND
@ ULAND
souffle::FunctorOp::EXP
@ EXP
souffle::FunctorOp::UMAX
@ UMAX
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
souffle::RamFloat
float RamFloat
Definition: RamTypes.h:60
TESTS_PER_OPERATION
#define TESTS_PER_OPERATION
Definition: ram_arithmetic_test.cpp:56
souffle::FunctorOp::NEG
@ NEG
Engine.h
souffle::FunctorOp::U2F
@ U2F
souffle::FunctorOp::FNEG
@ FNEG
souffle::FunctorOp::LNOT
@ LNOT
souffle::FunctorOp::BXOR
@ BXOR
souffle::FunctorOp::MOD
@ MOD
Program.h
Global.h
souffle::FunctorOp::UBNOT
@ UBNOT
souffle::FunctorOp::LOR
@ LOR
souffle::ram::TranslationUnit
Translating a RAM program.
Definition: TranslationUnit.h:55
souffle::SymbolTable::lookup
RamDomain lookup(const std::string &symbol)
Find the index of a symbol in the table, inserting a new symbol if it does not exist there already.
Definition: SymbolTable.h:124
i
size_t i
Definition: json11.h:663
souffle::FunctorOp::UMUL
@ UMUL
souffle::interpreter::test
Definition: interpreter_relation_test.cpp:28
souffle::FunctorOp::ULOR
@ ULOR
Relation.h
souffle::DebugReport
Class representing a HTML report, consisting of a list of sections.
Definition: DebugReport.h:87
souffle::SymbolTable
Definition: SymbolTable.h:48
souffle::FunctorOp::LAND
@ LAND
test.h
souffle::FunctorOp::SMAX
@ SMAX
souffle::FunctorOp::I2F
@ I2F
souffle::FunctorOp::BOR
@ BOR
souffle::FunctorOp::BNOT
@ BNOT
TranslationUnit.h
souffle::FunctorOp::FEXP
@ FEXP
souffle::FunctorOp
FunctorOp
Definition: FunctorOps.h:35
souffle::Global::config
static MainConfig & config()
Definition: Global.h:141
souffle::FunctorOp::UMIN
@ UMIN
souffle::interpreter::test::evalExpression
RamDomain evalExpression(Own< Expression > expression, SymbolTable &symTab)
Function to evaluate a single Expression.
Definition: ram_arithmetic_test.cpp:59
souffle::FunctorOp::F2I
@ F2I
souffle::FunctorOp::UMOD
@ UMOD
souffle::FunctorOp::FSUB
@ FSUB
souffle::FunctorOp::F2U
@ F2U
Query.h
souffle::FunctorOp::BAND
@ BAND
souffle::FunctorOp::UBAND
@ UBAND
souffle::FunctorOp::SUB
@ SUB
RamTypes.h
Sequence.h
Statement.h
souffle::FunctorOp::UDIV
@ UDIV
SignedConstant.h
souffle::interpreter::test::evalBinary
RamDomain evalBinary(FunctorOp functor, RamDomain arg1, RamDomain arg2)
Evaluate a binary operator.
Definition: ram_arithmetic_test.cpp:112
souffle::FunctorOp::UADD
@ UADD
SubroutineReturn.h
souffle::ramBitCast
To ramBitCast(From source)
In C++20 there will be a new way to cast between types by reinterpreting bits (std::bit_cast),...
Definition: RamTypes.h:87
souffle::FunctorOp::MUL
@ MUL
FunctorOps.h
Expression.h
souffle::FunctorOp::SMIN
@ SMIN
souffle::FunctorOp::ADD
@ ADD
Binary Functor Operators.
souffle::ErrorReport
Definition: ErrorReport.h:152
souffle::VecOwn
std::vector< Own< A > > VecOwn
Definition: ContainerUtil.h:45
ErrorReport.h
souffle::interpreter::test::TEST
TEST(Relation0, Construction)
Definition: interpreter_relation_test.cpp:38
souffle::FunctorOp::MAX
@ MAX
souffle::FunctorOp::FMAX
@ FMAX
IntrinsicOperator.h
souffle::interpreter::test::evalUnary
RamDomain evalUnary(FunctorOp functor, RamDomain arg1)
Evaluate a single argument expression.
Definition: ram_arithmetic_test.cpp:104
souffle::FunctorOp::I2U
@ I2U
souffle::FunctorOp::MIN
@ MIN
souffle::FunctorOp::ULNOT
@ ULNOT