1 // { dg-do compile }
2 // { dg-require-effective-target c++11 }
3 // { dg-require-effective-target vect_double }
4 // For MIN/MAX recognition
5 // { dg-additional-options "-ffast-math" }
6 
7 #include <algorithm>
8 #include <cmath>
9 #include <stdint.h>
10 
11 // Point structure [x, y]
12 struct Point {
13   double x, y;
14 
15   inline Point() noexcept = default;
16   constexpr Point(const Point&) noexcept = default;
17 
PointPoint18   constexpr Point(double x, double y) noexcept
19     : x(x), y(y) {}
20 };
21 
22 // Box structure [x0, y0, x1, y1]
23 struct Box {
24   double x0, y0, x1, y1;
25 
resetBox26   inline void reset(double x0, double y0, double x1, double y1) noexcept {
27     this->x0 = x0;
28     this->y0 = y0;
29     this->x1 = x1;
30     this->y1 = y1;
31   }
32 };
33 
34 // Overloads to make vector processing simpler.
operator -(const Point & a)35 static constexpr Point operator-(const Point& a) noexcept { return Point(-a.x, -a.y); }
36 
operator +(const Point & a,double b)37 static constexpr Point operator+(const Point& a, double b) noexcept
38 { return Point(a.x + b, a.y + b); }
operator -(const Point & a,double b)39 static constexpr Point operator-(const Point& a, double b) noexcept
40 { return Point(a.x - b, a.y - b); }
operator *(const Point & a,double b)41 static constexpr Point operator*(const Point& a, double b) noexcept
42 { return Point(a.x * b, a.y * b); }
operator /(const Point & a,double b)43 static constexpr Point operator/(const Point& a, double b) noexcept
44 { return Point(a.x / b, a.y / b); }
45 
operator +(const Point & a,const Point & b)46 static constexpr Point operator+(const Point& a, const Point& b) noexcept
47 { return Point(a.x + b.x, a.y + b.y); }
operator -(const Point & a,const Point & b)48 static constexpr Point operator-(const Point& a, const Point& b) noexcept
49 { return Point(a.x - b.x, a.y - b.y); }
operator *(const Point & a,const Point & b)50 static constexpr Point operator*(const Point& a, const Point& b) noexcept
51 { return Point(a.x * b.x, a.y * b.y); }
operator /(const Point & a,const Point & b)52 static constexpr Point operator/(const Point& a, const Point& b) noexcept
53 { return Point(a.x / b.x, a.y / b.y); }
54 
operator +(double a,const Point & b)55 static constexpr Point operator+(double a, const Point& b) noexcept
56 { return Point(a + b.x, a + b.y); }
operator -(double a,const Point & b)57 static constexpr Point operator-(double a, const Point& b) noexcept
58 { return Point(a - b.x, a - b.y); }
operator *(double a,const Point & b)59 static constexpr Point operator*(double a, const Point& b) noexcept
60 { return Point(a * b.x, a * b.y); }
operator /(double a,const Point & b)61 static constexpr Point operator/(double a, const Point& b) noexcept
62 { return Point(a / b.x, a / b.y); }
63 
64 // Min/Max - different semantics compared to std.
myMin(const T & a,const T & b)65 template<typename T> constexpr T myMin(const T& a, const T& b) noexcept
66 { return b < a ? b : a; }
myMax(const T & a,const T & b)67 template<typename T> constexpr T myMax(const T& a, const T& b) noexcept
68 { return a < b ? b : a; }
69 
70 // Linear interpolation, works with points as well.
71 template<typename V, typename T = double>
lerp(const V & a,const V & b,const T & t)72 inline V lerp(const V& a, const V& b, const T& t) noexcept {
73   return (a * (1.0 - t)) + (b * t);
74 }
75 
76 // Merge a point into a box by possibly increasing its bounds.
boxMergePoint(Box & box,const Point & p)77 inline void boxMergePoint(Box& box, const Point& p) noexcept {
78   box.x0 = myMin(box.x0, p.x);
79   box.y0 = myMin(box.y0, p.y);
80   box.x1 = myMax(box.x1, p.x);
81   box.y1 = myMax(box.y1, p.y);
82 }
83 
quadBoundingBoxA(const Point bez[3],Box & bBox)84 void quadBoundingBoxA(const Point bez[3], Box& bBox) noexcept {
85   // Bounding box of start and end points.
86   bBox.reset(myMin(bez[0].x, bez[2].x), myMin(bez[0].y, bez[2].y),
87              myMax(bez[0].x, bez[2].x), myMax(bez[0].y, bez[2].y));
88 
89   Point t = (bez[0] - bez[1]) / (bez[0] - bez[1] * 2.0 + bez[2]);
90 
91   t.x = myMax(t.x, 0.0);
92   t.y = myMax(t.y, 0.0);
93   t.x = myMin(t.x, 1.0);
94   t.y = myMin(t.y, 1.0);
95 
96   boxMergePoint(bBox, lerp(lerp(bez[0], bez[1], t),
97                                lerp(bez[1], bez[2], t), t));
98 }
99 
100 // We should have if-converted everything down to straight-line code
101 // { dg-final { scan-tree-dump-times "<bb \[0-9\]+>" 1 "slp2" } }
102 // { dg-final { scan-tree-dump-times "basic block part vectorized" 1 "slp2" { xfail { { ! vect_element_align } && { ! vect_hw_misalign } } } } }
103 // It's a bit awkward to detect that all stores were vectorized but the
104 // following more or less does the trick
105 // { dg-final { scan-tree-dump "vect_iftmp\[^\r\m\]* = MIN" "slp2" { xfail { { ! vect_element_align } && { ! vect_hw_misalign } } } } }
106