<commit_before>#include <vector>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>
#include <ctime>
#include <cstdio>
using namespace std;

// base and base_digits must be consistent
const int base = 1000000000;
const int base_digits = 9;

struct bigint {
    vector<int> a;
    int sign;

    bigint() :
        sign(1) {
    }

    bigint(long long v) {
        *this = v;
    }

    bigint(const string &s) {
        read(s);
    }

    void operator=(const bigint &v) {
        sign = v.sign;
        a = v.a;
    }

    void operator=(long long v) {
        sign = 1;
        if (v < 0)
            sign = -1, v = -v;
        a.clear();
        for (; v > 0; v = v / base)
            a.push_back(v % base);
    }

    bigint operator+(const bigint &v) const {
        if (sign == v.sign) {
            bigint res = v;

            for (int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
                if (i == (int) res.a.size())
                    res.a.push_back(0);
                res.a[i] += carry + (i < (int) a.size() ? a[i] : 0);
                carry = res.a[i] >= base;
                if (carry)
                    res.a[i] -= base;
            }
            return res;
        }
        return *this - (-v);
    }

    bigint operator-(const bigint &v) const {
        if (sign == v.sign) {
            if (abs() >= v.abs()) {
                bigint res = *this;
                for (int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) {
                    res.a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0);
                    carry = res.a[i] < 0;
                    if (carry)
                        res.a[i] += base;
                }
                res.trim();
                return res;
            }
            return -(v - *this);
        }
        return *this + (-v);
    }

    void operator*=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = 0, carry = 0; i < (int) a.size() || carry; ++i) {
            if (i == (int) a.size())
                a.push_back(0);
            long long cur = a[i] * (long long) v + carry;
            carry = (int) (cur / base);
            a[i] = (int) (cur % base);
            //asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
        }
        trim();
    }

    bigint operator*(int v) const {
        bigint res = *this;
        res *= v;
        return res;
    }

    friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
        int norm = base / (b1.a.back() + 1);
        bigint a = a1.abs() * norm;
        bigint b = b1.abs() * norm;
        bigint q, r;
        q.a.resize(a.a.size());

        for (int i = a.a.size() - 1; i >= 0; i--) {
            r *= base;
            r += a.a[i];
            int s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()];
            int s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1];
            int d = ((long long) base * s1 + s2) / b.a.back();
            r -= b * d;
            while (r < 0)
                r += b, --d;
            q.a[i] = d;
        }

        q.sign = a1.sign * b1.sign;
        r.sign = a1.sign;
        q.trim();
        r.trim();
        return make_pair(q, r / norm);
    }

    bigint operator/(const bigint &v) const {
        return divmod(*this, v).first;
    }

    bigint operator%(const bigint &v) const {
        return divmod(*this, v).second;
    }

    void operator/=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = (int) a.size() - 1, rem = 0; i >= 0; --i) {
            long long cur = a[i] + rem * (long long) base;
            a[i] = (int) (cur / v);
            rem = (int) (cur % v);
        }
        trim();
    }

    bigint operator/(int v) const {
        bigint res = *this;
        res /= v;
        return res;
    }

    int operator%(int v) const {
        if (v < 0)
            v = -v;
        int m = 0;
        for (int i = a.size() - 1; i >= 0; --i)
            m = (a[i] + m * (long long) base) % v;
        return m * sign;
    }

    void operator+=(const bigint &v) {
        *this = *this + v;
    }
    void operator-=(const bigint &v) {
        *this = *this - v;
    }
    void operator*=(const bigint &v) {
        *this = *this * v;
    }
    void operator/=(const bigint &v) {
        *this = *this / v;
    }

    bool operator<(const bigint &v) const {
        if (sign != v.sign)
            return sign < v.sign;
        if (a.size() != v.a.size())
            return a.size() * sign < v.a.size() * v.sign;
        for (int i = a.size() - 1; i >= 0; i--)
            if (a[i] != v.a[i])
                return a[i] * sign < v.a[i] * sign;
        return false;
    }

    bool operator>(const bigint &v) const {
        return v < *this;
    }
    bool operator<=(const bigint &v) const {
        return !(v < *this);
    }
    bool operator>=(const bigint &v) const {
        return !(*this < v);
    }
    bool operator==(const bigint &v) const {
        return !(*this < v) && !(v < *this);
    }
    bool operator!=(const bigint &v) const {
        return *this < v || v < *this;
    }

    void trim() {
        while (!a.empty() && a.back() == 0)
            a.pop_back();
        if (a.empty())
            sign = 1;
    }

    bool isZero() const {
        return a.empty() || (a.size() == 1 && !a[0]);
    }

    bigint operator-() const {
        bigint res = *this;
        res.sign = -sign;
        return res;
    }

    bigint abs() const {
        bigint res = *this;
        res.sign *= res.sign;
        return res;
    }

    long long longValue() const {
        long long res = 0;
        for (int i = a.size() - 1; i >= 0; i--)
            res = res * base + a[i];
        return res * sign;
    }

    friend bigint gcd(const bigint &a, const bigint &b) {
        return b.isZero() ? a : gcd(b, a % b);
    }
    friend bigint lcm(const bigint &a, const bigint &b) {
        return a / gcd(a, b) * b;
    }

    void read(const string &s) {
        sign = 1;
        a.clear();
        int pos = 0;
        while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
            if (s[pos] == '-')
                sign = -sign;
            ++pos;
        }
        for (int i = s.size() - 1; i >= pos; i -= base_digits) {
            int x = 0;
            for (int j = max(pos, i - base_digits + 1); j <= i; j++)
                x = x * 10 + s[j] - '0';
            a.push_back(x);
        }
        trim();
    }

    friend istream& operator>>(istream &stream, bigint &v) {
        string s;
        stream >> s;
        v.read(s);
        return stream;
    }

    friend ostream& operator<<(ostream &stream, const bigint &v) {
        if (v.sign == -1)
            stream << '-';
        stream << (v.a.empty() ? 0 : v.a.back());
        for (int i = (int) v.a.size() - 2; i >= 0; --i)
            stream << setw(base_digits) << setfill('0') << v.a[i];
        return stream;
    }

    static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) {
        vector<long long> p(max(old_digits, new_digits) + 1);
        p[0] = 1;
        for (int i = 1; i < (int) p.size(); i++)
            p[i] = p[i - 1] * 10;
        vector<int> res;
        long long cur = 0;
        int cur_digits = 0;
        for (int i = 0; i < (int) a.size(); i++) {
            cur += a[i] * p[cur_digits];
            cur_digits += old_digits;
            while (cur_digits >= new_digits) {
                res.push_back(int(cur % p[new_digits]));
                cur /= p[new_digits];
                cur_digits -= new_digits;
            }
        }
        res.push_back((int) cur);
        while (!res.empty() && res.back() == 0)
            res.pop_back();
        return res;
    }

    typedef vector<long long> vll;

    static vll karatsubaMultiply(const vll &a, const vll &b) {
        int n = a.size();
        vll res(n + n);
        if (n <= 32) {
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    res[i + j] += a[i] * b[j];
            return res;
        }

        int k = n >> 1;
        vll a1(a.begin(), a.begin() + k);
        vll a2(a.begin() + k, a.end());
        vll b1(b.begin(), b.begin() + k);
        vll b2(b.begin() + k, b.end());

        vll a1b1 = karatsubaMultiply(a1, b1);
        vll a2b2 = karatsubaMultiply(a2, b2);

        for (int i = 0; i < k; i++)
            a2[i] += a1[i];
        for (int i = 0; i < k; i++)
            b2[i] += b1[i];

        vll r = karatsubaMultiply(a2, b2);
        for (int i = 0; i < (int) a1b1.size(); i++)
            r[i] -= a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            r[i] -= a2b2[i];

        for (int i = 0; i < (int) r.size(); i++)
            res[i + k] += r[i];
        for (int i = 0; i < (int) a1b1.size(); i++)
            res[i] += a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            res[i + n] += a2b2[i];
        return res;
    }

    bigint operator*(const bigint &v) const {
        vector<int> a6 = convert_base(this->a, base_digits, 6);
        vector<int> b6 = convert_base(v.a, base_digits, 6);
        vll a(a6.begin(), a6.end());
        vll b(b6.begin(), b6.end());
        while (a.size() < b.size())
            a.push_back(0);
        while (b.size() < a.size())
            b.push_back(0);
        while (a.size() & (a.size() - 1))
            a.push_back(0), b.push_back(0);
        vll c = karatsubaMultiply(a, b);
        bigint res;
        res.sign = sign * v.sign;
        for (int i = 0, carry = 0; i < (int) c.size(); i++) {
            long long cur = c[i] + carry;
            res.a.push_back((int) (cur % 1000000));
            carry = (int) (cur / 1000000);
        }
        res.a = convert_base(res.a, 6, base_digits);
        res.trim();
        return res;
    }
};

int main() {
    bigint a("99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999");
    bigint b("19999999999999999999999999999999999999999999999999999999999999999999999999999999999999998");
    cout << a * b << endl;
    cout << a / b << endl;

    string sa, sb;
    for (int i = 0; i < 100000; i++)
        sa += i % 10 + '0';
    for (int i = 0; i < 20000; i++)
        sb += i % 10 + '0';
    a = bigint(sa);
    b = bigint(sb);

    clock_t start = clock();
    bigint c = a / b;
    fprintf(stderr, "time=%.3lfsec\n", 0.001 * (clock() - start));

    bigint x = 5;
    x = 6;
    cout << x << endl;
}
<commit_msg>update<commit_after>#include <vector>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>
#include <ctime>
#include <cstdio>
#include <cmath>
using namespace std;

// base and base_digits must be consistent
const int base = 1000000000;
const int base_digits = 9;

struct bigint {
    vector<int> z;
    int sign;

    bigint() :
        sign(1) {
    }

    bigint(long long v) {
        *this = v;
    }

    bigint(const string &s) {
        read(s);
    }

    void operator=(const bigint &v) {
        sign = v.sign;
        z = v.z;
    }

    void operator=(long long v) {
        sign = 1;
        if (v < 0)
            sign = -1, v = -v;
        z.clear();
        for (; v > 0; v = v / base)
            z.push_back(v % base);
    }

    bigint operator+(const bigint &v) const {
        if (sign == v.sign) {
            bigint res = v;

            for (int i = 0, carry = 0; i < (int) max(z.size(), v.z.size()) || carry; ++i) {
                if (i == (int) res.z.size())
                    res.z.push_back(0);
                res.z[i] += carry + (i < (int) z.size() ? z[i] : 0);
                carry = res.z[i] >= base;
                if (carry)
                    res.z[i] -= base;
            }
            return res;
        }
        return *this - (-v);
    }

    bigint operator-(const bigint &v) const {
        if (sign == v.sign) {
            if (abs() >= v.abs()) {
                bigint res = *this;
                for (int i = 0, carry = 0; i < (int) v.z.size() || carry; ++i) {
                    res.z[i] -= carry + (i < (int) v.z.size() ? v.z[i] : 0);
                    carry = res.z[i] < 0;
                    if (carry)
                        res.z[i] += base;
                }
                res.trim();
                return res;
            }
            return -(v - *this);
        }
        return *this + (-v);
    }

    void operator*=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = 0, carry = 0; i < (int) z.size() || carry; ++i) {
            if (i == (int) z.size())
                z.push_back(0);
            long long cur = z[i] * (long long) v + carry;
            carry = (int) (cur / base);
            z[i] = (int) (cur % base);
            //asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
        }
        trim();
    }

    bigint operator*(int v) const {
        bigint res = *this;
        res *= v;
        return res;
    }

    friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
        int norm = base / (b1.z.back() + 1);
        bigint a = a1.abs() * norm;
        bigint b = b1.abs() * norm;
        bigint q, r;
        q.z.resize(a.z.size());

        for (int i = a.z.size() - 1; i >= 0; i--) {
            r *= base;
            r += a.z[i];
            int s1 = b.z.size() < r.z.size() ? r.z[b.z.size()] : 0;
            int s2 = b.z.size() - 1 < r.z.size() ? r.z[b.z.size() - 1] : 0;
            int d = ((long long) s1 * base + s2) / b.z.back();
            r -= b * d;
            while (r < 0)
                r += b, --d;
            q.z[i] = d;
        }

        q.sign = a1.sign * b1.sign;
        r.sign = a1.sign;
        q.trim();
        r.trim();
        return make_pair(q, r / norm);
    }

    friend bigint sqrt(const bigint &a1) {
        bigint a = a1;
        while (a.z.empty() || a.z.size() % 2 == 1)
            a.z.push_back(0);

        int n = a.z.size();

        int firstDigit = (int) sqrt((double) a.z[n - 1] * base + a.z[n - 2]);
        int norm = base / (firstDigit + 1);
        a *= norm;
        a *= norm;
		while (a.z.empty() || a.z.size() % 2 == 1)
			a.z.push_back(0);

        bigint r = (long long) a.z[n - 1] * base + a.z[n - 2];
        firstDigit = (int) sqrt((double) a.z[n - 1] * base + a.z[n - 2]);
        int q = firstDigit;
		bigint res;

        for(int j = n / 2 - 1; j >= 0; j--) {
            for(; ; --q) {
                bigint r1 = (r - (res * 2 * base + q) * q) * base * base + (j > 0 ? (long long) a.z[2 * j - 1] * base + a.z[2 * j - 2] : 0);
                if (r1 >= 0) {
                    r = r1;
                    break;
                }
            }
            res *= base;
            res += q;

            if (j > 0) {
				int d1 = res.z.size() + 2 < r.z.size() ? r.z[res.z.size() + 2] : 0;
				int d2 = res.z.size() + 1 < r.z.size() ? r.z[res.z.size() + 1] : 0;
                int d3 = res.z.size() < r.z.size() ? r.z[res.z.size()] : 0;
                q = ((long long) d1 * base * base + (long long) d2 * base + d3) / (firstDigit * 2);
            }
        }

        res.trim();
        return res / norm;
    }

    bigint operator/(const bigint &v) const {
        return divmod(*this, v).first;
    }

    bigint operator%(const bigint &v) const {
        return divmod(*this, v).second;
    }

    void operator/=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = (int) z.size() - 1, rem = 0; i >= 0; --i) {
            long long cur = z[i] + rem * (long long) base;
            z[i] = (int) (cur / v);
            rem = (int) (cur % v);
        }
        trim();
    }

    bigint operator/(int v) const {
        bigint res = *this;
        res /= v;
        return res;
    }

    int operator%(int v) const {
        if (v < 0)
            v = -v;
        int m = 0;
        for (int i = z.size() - 1; i >= 0; --i)
            m = (z[i] + m * (long long) base) % v;
        return m * sign;
    }

    void operator+=(const bigint &v) {
        *this = *this + v;
    }
    void operator-=(const bigint &v) {
        *this = *this - v;
    }
    void operator*=(const bigint &v) {
        *this = *this * v;
    }
    void operator/=(const bigint &v) {
        *this = *this / v;
    }

    bool operator<(const bigint &v) const {
        if (sign != v.sign)
            return sign < v.sign;
        if (z.size() != v.z.size())
            return z.size() * sign < v.z.size() * v.sign;
        for (int i = z.size() - 1; i >= 0; i--)
            if (z[i] != v.z[i])
                return z[i] * sign < v.z[i] * sign;
        return false;
    }

    bool operator>(const bigint &v) const {
        return v < *this;
    }
    bool operator<=(const bigint &v) const {
        return !(v < *this);
    }
    bool operator>=(const bigint &v) const {
        return !(*this < v);
    }
    bool operator==(const bigint &v) const {
        return !(*this < v) && !(v < *this);
    }
    bool operator!=(const bigint &v) const {
        return *this < v || v < *this;
    }

    void trim() {
        while (!z.empty() && z.back() == 0)
            z.pop_back();
        if (z.empty())
            sign = 1;
    }

    bool isZero() const {
        return z.empty() || (z.size() == 1 && !z[0]);
    }

    bigint operator-() const {
        bigint res = *this;
        res.sign = -sign;
        return res;
    }

    bigint abs() const {
        bigint res = *this;
        res.sign *= res.sign;
        return res;
    }

    long long longValue() const {
        long long res = 0;
        for (int i = z.size() - 1; i >= 0; i--)
            res = res * base + z[i];
        return res * sign;
    }

    friend bigint gcd(const bigint &a, const bigint &b) {
        return b.isZero() ? a : gcd(b, a % b);
    }
    friend bigint lcm(const bigint &a, const bigint &b) {
        return a / gcd(a, b) * b;
    }

    void read(const string &s) {
        sign = 1;
        z.clear();
        int pos = 0;
        while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
            if (s[pos] == '-')
                sign = -sign;
            ++pos;
        }
        for (int i = s.size() - 1; i >= pos; i -= base_digits) {
            int x = 0;
            for (int j = max(pos, i - base_digits + 1); j <= i; j++)
                x = x * 10 + s[j] - '0';
            z.push_back(x);
        }
        trim();
    }

    friend istream& operator>>(istream &stream, bigint &v) {
        string s;
        stream >> s;
        v.read(s);
        return stream;
    }

    friend ostream& operator<<(ostream &stream, const bigint &v) {
        if (v.sign == -1)
            stream << '-';
        stream << (v.z.empty() ? 0 : v.z.back());
        for (int i = (int) v.z.size() - 2; i >= 0; --i)
            stream << setw(base_digits) << setfill('0') << v.z[i];
        return stream;
    }

    static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) {
        vector<long long> p(max(old_digits, new_digits) + 1);
        p[0] = 1;
        for (int i = 1; i < (int) p.size(); i++)
            p[i] = p[i - 1] * 10;
        vector<int> res;
        long long cur = 0;
        int cur_digits = 0;
        for (int i = 0; i < (int) a.size(); i++) {
            cur += a[i] * p[cur_digits];
            cur_digits += old_digits;
            while (cur_digits >= new_digits) {
                res.push_back(int(cur % p[new_digits]));
                cur /= p[new_digits];
                cur_digits -= new_digits;
            }
        }
        res.push_back((int) cur);
        while (!res.empty() && res.back() == 0)
            res.pop_back();
        return res;
    }

    typedef vector<long long> vll;

    static vll karatsubaMultiply(const vll &a, const vll &b) {
        int n = a.size();
        vll res(n + n);
        if (n <= 32) {
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    res[i + j] += a[i] * b[j];
            return res;
        }

        int k = n >> 1;
        vll a1(a.begin(), a.begin() + k);
        vll a2(a.begin() + k, a.end());
        vll b1(b.begin(), b.begin() + k);
        vll b2(b.begin() + k, b.end());

        vll a1b1 = karatsubaMultiply(a1, b1);
        vll a2b2 = karatsubaMultiply(a2, b2);

        for (int i = 0; i < k; i++)
            a2[i] += a1[i];
        for (int i = 0; i < k; i++)
            b2[i] += b1[i];

        vll r = karatsubaMultiply(a2, b2);
        for (int i = 0; i < (int) a1b1.size(); i++)
            r[i] -= a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            r[i] -= a2b2[i];

        for (int i = 0; i < (int) r.size(); i++)
            res[i + k] += r[i];
        for (int i = 0; i < (int) a1b1.size(); i++)
            res[i] += a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            res[i + n] += a2b2[i];
        return res;
    }

    bigint operator*(const bigint &v) const {
        vector<int> a6 = convert_base(this->z, base_digits, 6);
        vector<int> b6 = convert_base(v.z, base_digits, 6);
        vll a(a6.begin(), a6.end());
        vll b(b6.begin(), b6.end());
        while (a.size() < b.size())
            a.push_back(0);
        while (b.size() < a.size())
            b.push_back(0);
        while (a.size() & (a.size() - 1))
            a.push_back(0), b.push_back(0);
        vll c = karatsubaMultiply(a, b);
        bigint res;
        res.sign = sign * v.sign;
        for (int i = 0, carry = 0; i < (int) c.size(); i++) {
            long long cur = c[i] + carry;
            res.z.push_back((int) (cur % 1000000));
            carry = (int) (cur / 1000000);
        }
        res.z = convert_base(res.z, 6, base_digits);
        res.trim();
        return res;
    }
};

bigint random_bigint(int n) {
	string s;
	for (int i = 0; i < n; i++) {
		s += rand() % 10 + '0';
	}
	return bigint(s);
}

// random tests
int main() {
	for(int i = 0; i < 1000; i++) {
		cout << i << endl;
		int n = rand() % 100 + 1;
		bigint a = random_bigint(n);
		bigint res = sqrt(a);
		bigint xx = res * res;
		bigint yy = (res + 1) * (res + 1);

		if (xx > a || yy <= a) {
			cout << a << " " << res << endl;
			break;
		}

		int m = rand() % n + 1;
		bigint b = random_bigint(m) + 1;
		res = a / b;
		xx = res * b;
		yy = b * (res + 1);

		if (xx > a || yy <= a) {
			cout << a << " " << b << " " << res << endl;
			break;
		}
	}

    bigint a = random_bigint(10000);
	bigint b = random_bigint(2000);
    clock_t start = clock();
    bigint c = a / b;
    fprintf(stdout, "time=%.3lfsec\n", 0.001 * (clock() - start));

    bigint x = 5;
    x = 6;
    cout << x << endl;
}
<|endoftext|>


<commit_before>#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#include <boost/test/unit_test.hpp>
#pragma GCC diagnostic pop
#include <boost/algorithm/string/predicate.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>

#include <tic_tac_toe/tic_tac_toe.wast.hpp>
#include <tic_tac_toe/tic_tac_toe.abi.hpp>
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>

#include <proxy/proxy.wast.hpp>
#include <proxy/proxy.abi.hpp>

#include <Runtime/Runtime.h>

#include <fc/variant_object.hpp>
#include <fc/io/json.hpp>

#ifdef NON_VALIDATING_TEST
#define TESTER tester
#else
#define TESTER validating_tester
#endif

using namespace eosio;
using namespace eosio::chain;
using namespace eosio::chain::contracts;
using namespace eosio::testing;
using namespace fc;

struct movement {
   uint32_t    row;
   uint32_t    column;

   template<typename DataStream>
   friend DataStream& operator << ( DataStream& ds, const movement& t ){ \
      return ds << t.row << t.column;
   }
   template<typename DataStream>
   friend DataStream& operator >> ( DataStream& ds, movement& t ){
      return ds >> t.row >> t.column;
   }
};

BOOST_AUTO_TEST_SUITE(tic_tac_toe_tests)

BOOST_AUTO_TEST_CASE( tic_tac_toe_game ) try {
   TESTER chain;
   abi_serializer abi_ser = json::from_string(tic_tac_toe_abi).as<abi_def>();

   chain.set_code(config::system_account_name, eosio_system_wast);
   chain.set_abi(config::system_account_name, eosio_system_abi);

   chain.produce_blocks();
   chain.create_account(N(tic.tac.toe));
   chain.produce_blocks(10);

   chain.set_code(N(tic.tac.toe), tic_tac_toe_wast);
   chain.set_abi(N(tic.tac.toe), tic_tac_toe_abi);

   chain.produce_blocks();
   chain.create_account(N(player1));
   chain.create_account(N(player2));
   chain.produce_blocks(10);

   chain.push_action(N(tic.tac.toe), N(create), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
   );

   chain.produce_blocks();

   auto mvt = mutable_variant_object()
           ("row", 1)
           ("column", 1);
   chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player1")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 1);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player1")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("not your turn"));

   mvt = mutable_variant_object()
           ("row", 1)
           ("column", 1);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("not a valid movement"));

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 1);
   chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player2")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 0 );
   chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player1")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 2);
   chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player2")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 2)
           ("column", 2);
   chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player1")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 2)
           ("column", 0);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("the game has ended"));

   chain.push_action(N(tic.tac.toe), N(close), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
   );

   mvt = mutable_variant_object()
           ("row", 2)
           ("column", 0);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("game doesn't exists"));

   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(restart), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
      ), transaction_exception, assert_message_contains("game doesn't exists"));

   chain.push_action(N(tic.tac.toe), N(create), N(player2), mutable_variant_object()
           ("challenger", "player1")
           ("host", "player2")
   );

   chain.push_action(N(tic.tac.toe), N(restart), N(player1), mutable_variant_object()
           ("challenger", "player1")
           ("host", "player2")
           ("by", "player1")
   );

   // making a move and ...
   mvt = mutable_variant_object()
           ("row", 1)
           ("column", 1);
   chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
           ("challenger", "player1")
           ("host", "player2")
           ("by", "player2")
           ("mvt", mvt)
   );

   // ... repeating to get exception to ensure restart above actually did something
   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 1);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player1")
         ("host", "player2")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("not your turn"));
} FC_LOG_AND_RETHROW()

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fixes for peer review and extra cleanup. GH #2214<commit_after>#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#include <boost/test/unit_test.hpp>
#pragma GCC diagnostic pop
#include <boost/algorithm/string/predicate.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>

#include <tic_tac_toe/tic_tac_toe.wast.hpp>
#include <tic_tac_toe/tic_tac_toe.abi.hpp>
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>

#include <proxy/proxy.wast.hpp>
#include <proxy/proxy.abi.hpp>

#include <Runtime/Runtime.h>

#include <fc/variant_object.hpp>
#include <fc/io/json.hpp>

#ifdef NON_VALIDATING_TEST
#define TESTER tester
#else
#define TESTER validating_tester
#endif

using namespace eosio;
using namespace eosio::chain;
using namespace eosio::chain::contracts;
using namespace eosio::testing;
using namespace fc;

const static uint32_t board_len = 9;
struct game {
   account_name     challenger;
   account_name     host;
   account_name     turn; // = account name of host/ challenger
   account_name     winner = N(none); // = none/ draw/ account name of host/ challenger
   uint8_t          board[board_len];
};
FC_REFLECT(game, (challenger)(host)(turn)(winner)(board));

struct movement {
   uint32_t    row;
   uint32_t    column;
};
FC_REFLECT(movement, (row)(column));

struct ttt_tester : TESTER {
   void get_game(game& game, account_name scope, account_name key) {
      auto* maybe_tid = find_table(N(tic.tac.toe), scope, N(games));
      if(maybe_tid == nullptr)
         BOOST_FAIL("table for code=\"tic.tac.toe\" scope=\"" + scope.to_string() + "\" table=\"games\" does not exist");

      auto* o = control->get_database().find<contracts::key_value_object, contracts::by_scope_primary>(boost::make_tuple(maybe_tid->id, key));
      if(o == nullptr)
         BOOST_FAIL("game for  does not exist for challenger=\"" + key.to_string() + "\"");

      fc::raw::unpack(o->value.data(), o->value.size(), game);
   }
};

BOOST_AUTO_TEST_SUITE(tic_tac_toe_tests)

BOOST_AUTO_TEST_CASE( tic_tac_toe_game ) try {
   TESTER chain;
   abi_serializer abi_ser = json::from_string(tic_tac_toe_abi).as<abi_def>();
   chain.create_account(N(tic.tac.toe));
   chain.produce_blocks(10);

   chain.set_code(N(tic.tac.toe), tic_tac_toe_wast);
   chain.set_abi(N(tic.tac.toe), tic_tac_toe_abi);

   chain.produce_blocks();
   chain.create_account(N(player1));
   chain.create_account(N(player2));
   chain.produce_blocks(10);

   chain.push_action(N(tic.tac.toe), N(create), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
   );

   chain.produce_blocks();

   auto mvt = mutable_variant_object()
           ("row", 1)
           ("column", 1);
   chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player1")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 1);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player1")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("not your turn"));

   mvt = mutable_variant_object()
           ("row", 1)
           ("column", 1);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("not a valid movement"));

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 1);
   chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player2")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 0 );
   chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player1")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 2);
   chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player2")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 2)
           ("column", 2);
   chain.push_action(N(tic.tac.toe), N(move), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
           ("by", "player1")
           ("mvt", mvt)
   );

   mvt = mutable_variant_object()
           ("row", 2)
           ("column", 0);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("the game has ended"));

   game current;
   chain.get_table_entry(current, N(tic.tac.toe), N(player1), N(games), N(player2));
   BOOST_REQUIRE_EQUAL("player1", account_name(current.winner).to_string());

   chain.push_action(N(tic.tac.toe), N(close), N(player1), mutable_variant_object()
           ("challenger", "player2")
           ("host", "player1")
   );

   mvt = mutable_variant_object()
           ("row", 2)
           ("column", 0);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("game doesn't exists"));

   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(restart), N(player2), mutable_variant_object()
         ("challenger", "player2")
         ("host", "player1")
         ("by", "player2")
      ), transaction_exception, assert_message_contains("game doesn't exists"));

   chain.push_action(N(tic.tac.toe), N(create), N(player2), mutable_variant_object()
           ("challenger", "player1")
           ("host", "player2")
   );

   chain.push_action(N(tic.tac.toe), N(restart), N(player1), mutable_variant_object()
           ("challenger", "player1")
           ("host", "player2")
           ("by", "player1")
   );

   // making a move and ...
   mvt = mutable_variant_object()
           ("row", 1)
           ("column", 1);
   chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
           ("challenger", "player1")
           ("host", "player2")
           ("by", "player2")
           ("mvt", mvt)
   );

   // ... repeating to get exception to ensure restart above actually did something
   mvt = mutable_variant_object()
           ("row", 0)
           ("column", 1);
   BOOST_CHECK_EXCEPTION(chain.push_action(N(tic.tac.toe), N(move), N(player2), mutable_variant_object()
         ("challenger", "player1")
         ("host", "player2")
         ("by", "player2")
         ("mvt", mvt)
      ), transaction_exception, assert_message_contains("not your turn"));
} FC_LOG_AND_RETHROW()

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "../../unittestpp.h"
#include "RecordingReporter.h"

using namespace UnitTest;

namespace {

TEST(CheckEqualWithUnsignedLong)
{
    TestResults results;
    unsigned long something = 2;
    CHECK_EQUAL(something, something);
}

TEST(CheckEqualsWithStringsFailsOnDifferentStrings)
{
    char txt1[] = "Hello";
    char txt2[] = "Hallo";
    TestResults results;
    CheckEqual(results, txt1, txt2, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

char txt1[] = "Hello"; // non-const on purpose so no folding of duplicate data
char txt2[] = "Hello";

TEST(CheckEqualsWithStringsWorksOnContentsNonConstNonConst)
{
    char const* const p1 = txt1;
    char const* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsConstConst)
{
    char* const p1 = txt1;
    char* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsNonConstConst)
{
    char* const p1 = txt1;
    char const* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsConstNonConst)
{
    char const* const p1 = txt1;
    char* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsWithALiteral)
{
    char const* const p1 = txt1;
    TestResults results;
    CheckEqual(results, "Hello", p1, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualFailureIncludesCheckExpectedAndActual)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    const int something = 2;
    CheckEqual(results, 1, something, TestDetails("", "", "", 0));

	using namespace std;
    CHECK(strstr(reporter.lastFailedMessage, "xpected 1"));
    CHECK(strstr(reporter.lastFailedMessage, "was 2"));
}

TEST(CheckEqualFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("mytest", "mysuite", "file.h", 101);

    CheckEqual(results, 1, 2, details);

    CHECK_EQUAL("mytest", reporter.lastFailedTest);
    CHECK_EQUAL("mysuite", reporter.lastFailedSuite);
    CHECK_EQUAL("file.h", reporter.lastFailedFile);
    CHECK_EQUAL(101, reporter.lastFailedLine);
}

TEST(CheckCloseTrue)
{
    TestResults results;
    CheckClose(results, 3.001f, 3.0f, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckCloseFalse)
{
    TestResults results;
    CheckClose(results, 3.12f, 3.0f, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseWithZeroEpsilonWorksForSameNumber)
{
    TestResults results;
    CheckClose(results, 0.1f, 0.1f, 0, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckCloseWithNaNFails)
{
    union
    {
        unsigned int bitpattern;
        float nan;
    };
    bitpattern = 0xFFFFFFFF;
    TestResults results;
    CheckClose(results, 3.0f, nan, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseWithNaNAgainstItselfFails)
{
    union
    {
        unsigned int bitpattern;
        float nan;
    };
    bitpattern = 0xFFFFFFFF;
    TestResults results;
    CheckClose(results, nan, nan, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseFailureIncludesCheckExpectedAndActual)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    const float expected = 0.9f;
    const float actual = 1.1f;
    CheckClose(results, expected, actual, 0.01f, TestDetails("", "", "", 0));

	using namespace std;
    CHECK(strstr(reporter.lastFailedMessage, "xpected 0.9"));
    CHECK(strstr(reporter.lastFailedMessage, "was 1.1"));
}

TEST(CheckCloseFailureIncludesTolerance)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    CheckClose(results, 2, 3, 0.01f, TestDetails("", "", "", 0));

	using namespace std;
    CHECK(strstr(reporter.lastFailedMessage, "0.01"));
}

TEST(CheckCloseFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("mytest", "mysuite", "header.h", 10);

    CheckClose(results, 2, 3, 0.01f, details);

    CHECK_EQUAL("mytest", reporter.lastFailedTest);
    CHECK_EQUAL("mysuite", reporter.lastFailedSuite);
    CHECK_EQUAL("header.h", reporter.lastFailedFile);
    CHECK_EQUAL(10, reporter.lastFailedLine);
}

TEST(CheckArrayEqualTrue)
{
    TestResults results;

    int const array[3] = { 1, 2, 3 };
    CheckArrayEqual(results, array, array, 3, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckArrayEqualFalse)
{
    TestResults results;

    int const array1[3] = { 1, 2, 3 };
    int const array2[3] = { 1, 2, 2 };
    CheckArrayEqual(results, array1, array2, 3, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckArrayCloseTrue)
{
    TestResults results;

    float const array1[3] = { 1.0f, 1.5f, 2.0f };
    float const array2[3] = { 1.01f, 1.51f, 2.01f };
    CheckArrayClose(results, array1, array2, 3, 0.02f, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckArrayCloseFalse)
{
    TestResults results;

    float const array1[3] = { 1.0f, 1.5f, 2.0f };
    float const array2[3] = { 1.01f, 1.51f, 2.01f };
    CheckArrayClose(results, array1, array2, 3, 0.001f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckArrayCloseFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("arrayCloseTest", "arrayCloseSuite", "file", 1337);

    float const array1[3] = { 1.0f, 1.5f, 2.0f };
    float const array2[3] = { 1.01f, 1.51f, 2.01f };
    CheckArrayClose(results, array1, array2, 3, 0.001f, details);

    CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest);
    CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite);
    CHECK_EQUAL("file", reporter.lastFailedFile);
    CHECK_EQUAL(1337, reporter.lastFailedLine);
}

TEST(CheckArray2DCloseTrue)
{
    TestResults results;

    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
                                 { 2.0f, 2.5f, 3.0f },
                                 { 3.0f, 3.5f, 4.0f } };
    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
                                 { 2.01f, 2.51f, 3.01f },
                                 { 3.01f, 3.51f, 4.01f } };
    CheckArray2DClose(results, array1, array2, 3, 3, 0.02f, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckArray2DCloseFalse)
{
    TestResults results;

    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
                                 { 2.0f, 2.5f, 3.0f },
                                 { 3.0f, 3.5f, 4.0f } };
    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
                                 { 2.01f, 2.51f, 3.01f },
                                 { 3.01f, 3.51f, 4.01f } };
    CheckArray2DClose(results, array1, array2, 3, 3, 0.001f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseWithDoublesSucceeds)
{
    CHECK_CLOSE(0.5, 0.5, 0.0001);
}

TEST(CheckArray2DCloseFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("array2DCloseTest", "array2DCloseSuite", "file", 1234);

    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
                                 { 2.0f, 2.5f, 3.0f },
                                 { 3.0f, 3.5f, 4.0f } };
    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
                                 { 2.01f, 2.51f, 3.01f },
                                 { 3.01f, 3.51f, 4.01f } };
    CheckArray2DClose(results, array1, array2, 3, 3, 0.001f, details);

    CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest);
    CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite);
    CHECK_EQUAL("file", reporter.lastFailedFile);
    CHECK_EQUAL(1234, reporter.lastFailedLine);
}

}
<commit_msg>fix strict aliasing violation, was causing gcc failures.  use std::memcpy instead of union-cast<commit_after>#include "../../unittestpp.h"
#include "RecordingReporter.h"

#include <cstring>

using namespace UnitTest;

namespace {

TEST(CheckEqualWithUnsignedLong)
{
    TestResults results;
    unsigned long something = 2;
    CHECK_EQUAL(something, something);
}

TEST(CheckEqualsWithStringsFailsOnDifferentStrings)
{
    char txt1[] = "Hello";
    char txt2[] = "Hallo";
    TestResults results;
    CheckEqual(results, txt1, txt2, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

char txt1[] = "Hello"; // non-const on purpose so no folding of duplicate data
char txt2[] = "Hello";

TEST(CheckEqualsWithStringsWorksOnContentsNonConstNonConst)
{
    char const* const p1 = txt1;
    char const* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsConstConst)
{
    char* const p1 = txt1;
    char* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsNonConstConst)
{
    char* const p1 = txt1;
    char const* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsConstNonConst)
{
    char const* const p1 = txt1;
    char* const p2 = txt2;
    TestResults results;
    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualsWithStringsWorksOnContentsWithALiteral)
{
    char const* const p1 = txt1;
    TestResults results;
    CheckEqual(results, "Hello", p1, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckEqualFailureIncludesCheckExpectedAndActual)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    const int something = 2;
    CheckEqual(results, 1, something, TestDetails("", "", "", 0));

	using namespace std;
    CHECK(strstr(reporter.lastFailedMessage, "xpected 1"));
    CHECK(strstr(reporter.lastFailedMessage, "was 2"));
}

TEST(CheckEqualFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("mytest", "mysuite", "file.h", 101);

    CheckEqual(results, 1, 2, details);

    CHECK_EQUAL("mytest", reporter.lastFailedTest);
    CHECK_EQUAL("mysuite", reporter.lastFailedSuite);
    CHECK_EQUAL("file.h", reporter.lastFailedFile);
    CHECK_EQUAL(101, reporter.lastFailedLine);
}

TEST(CheckCloseTrue)
{
    TestResults results;
    CheckClose(results, 3.001f, 3.0f, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckCloseFalse)
{
    TestResults results;
    CheckClose(results, 3.12f, 3.0f, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseWithZeroEpsilonWorksForSameNumber)
{
    TestResults results;
    CheckClose(results, 0.1f, 0.1f, 0, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckCloseWithNaNFails)
{
	const unsigned int bitpattern = 0xFFFFFFFF;
	float nan;
	std::memcpy(&nan, &bitpattern, sizeof(bitpattern));

	TestResults results;
    CheckClose(results, 3.0f, nan, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseWithNaNAgainstItselfFails)
{
	const unsigned int bitpattern = 0xFFFFFFFF;
	float nan;
	std::memcpy(&nan, &bitpattern, sizeof(bitpattern));

    TestResults results;
    CheckClose(results, nan, nan, 0.1f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseFailureIncludesCheckExpectedAndActual)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    const float expected = 0.9f;
    const float actual = 1.1f;
    CheckClose(results, expected, actual, 0.01f, TestDetails("", "", "", 0));

	using namespace std;
    CHECK(strstr(reporter.lastFailedMessage, "xpected 0.9"));
    CHECK(strstr(reporter.lastFailedMessage, "was 1.1"));
}

TEST(CheckCloseFailureIncludesTolerance)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    CheckClose(results, 2, 3, 0.01f, TestDetails("", "", "", 0));

	using namespace std;
    CHECK(strstr(reporter.lastFailedMessage, "0.01"));
}

TEST(CheckCloseFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("mytest", "mysuite", "header.h", 10);

    CheckClose(results, 2, 3, 0.01f, details);

    CHECK_EQUAL("mytest", reporter.lastFailedTest);
    CHECK_EQUAL("mysuite", reporter.lastFailedSuite);
    CHECK_EQUAL("header.h", reporter.lastFailedFile);
    CHECK_EQUAL(10, reporter.lastFailedLine);
}

TEST(CheckArrayEqualTrue)
{
    TestResults results;

    int const array[3] = { 1, 2, 3 };
    CheckArrayEqual(results, array, array, 3, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckArrayEqualFalse)
{
    TestResults results;

    int const array1[3] = { 1, 2, 3 };
    int const array2[3] = { 1, 2, 2 };
    CheckArrayEqual(results, array1, array2, 3, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckArrayCloseTrue)
{
    TestResults results;

    float const array1[3] = { 1.0f, 1.5f, 2.0f };
    float const array2[3] = { 1.01f, 1.51f, 2.01f };
    CheckArrayClose(results, array1, array2, 3, 0.02f, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckArrayCloseFalse)
{
    TestResults results;

    float const array1[3] = { 1.0f, 1.5f, 2.0f };
    float const array2[3] = { 1.01f, 1.51f, 2.01f };
    CheckArrayClose(results, array1, array2, 3, 0.001f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckArrayCloseFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("arrayCloseTest", "arrayCloseSuite", "file", 1337);

    float const array1[3] = { 1.0f, 1.5f, 2.0f };
    float const array2[3] = { 1.01f, 1.51f, 2.01f };
    CheckArrayClose(results, array1, array2, 3, 0.001f, details);

    CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest);
    CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite);
    CHECK_EQUAL("file", reporter.lastFailedFile);
    CHECK_EQUAL(1337, reporter.lastFailedLine);
}

TEST(CheckArray2DCloseTrue)
{
    TestResults results;

    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
                                 { 2.0f, 2.5f, 3.0f },
                                 { 3.0f, 3.5f, 4.0f } };
    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
                                 { 2.01f, 2.51f, 3.01f },
                                 { 3.01f, 3.51f, 4.01f } };
    CheckArray2DClose(results, array1, array2, 3, 3, 0.02f, TestDetails("", "", "", 0));
    CHECK_EQUAL(0, results.GetFailureCount());
}

TEST(CheckArray2DCloseFalse)
{
    TestResults results;

    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
                                 { 2.0f, 2.5f, 3.0f },
                                 { 3.0f, 3.5f, 4.0f } };
    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
                                 { 2.01f, 2.51f, 3.01f },
                                 { 3.01f, 3.51f, 4.01f } };
    CheckArray2DClose(results, array1, array2, 3, 3, 0.001f, TestDetails("", "", "", 0));
    CHECK_EQUAL(1, results.GetFailureCount());
}

TEST(CheckCloseWithDoublesSucceeds)
{
    CHECK_CLOSE(0.5, 0.5, 0.0001);
}

TEST(CheckArray2DCloseFailureIncludesDetails)
{
    RecordingReporter reporter;
    TestResults results(&reporter);
    TestDetails const details("array2DCloseTest", "array2DCloseSuite", "file", 1234);

    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
                                 { 2.0f, 2.5f, 3.0f },
                                 { 3.0f, 3.5f, 4.0f } };
    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
                                 { 2.01f, 2.51f, 3.01f },
                                 { 3.01f, 3.51f, 4.01f } };
    CheckArray2DClose(results, array1, array2, 3, 3, 0.001f, details);

    CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest);
    CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite);
    CHECK_EQUAL("file", reporter.lastFailedFile);
    CHECK_EQUAL(1234, reporter.lastFailedLine);
}

}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.1  2001/11/09 09:11:24  morsch
Realisation of AliGenReader that reads the kine tree (TreeK).

*/
#include <TFile.h>
#include <TTree.h>
#include <TParticle.h>

#include "AliGenReaderTreeK.h"
#include "AliStack.h"
#include "AliHeader.h"
#include "AliRun.h"

ClassImp(AliGenReaderTreeK);

AliGenReaderTreeK::AliGenReaderTreeK():AliGenReader()
{
//  Default constructor
    fFileName       = NULL;
    fStack          = 0;
    fHeader         = 0;
    fNcurrent       = 0;
    fNparticle      = 0;
    fFile           = 0;
    fBaseFile       = 0;
    fTreeE          = 0;
}

AliGenReaderTreeK::~AliGenReaderTreeK()
{
// Destructor
    delete fTreeE;
}

void AliGenReaderTreeK::Init()
{
// Initialization
// Connect base file and file to read from

    TTree *ali = gAlice->TreeE();
    if (ali) {
	fBaseFile = ali->GetCurrentFile();
    } else {
	printf("\n Warning: Basefile cannot be found !\n");
    }
    fFile = new TFile(fFileName);
}

Int_t AliGenReaderTreeK::NextEvent()
{
// Read the next event
//  cd to file with old kine tree
    if (!fBaseFile) Init();
    if (fStack) delete fStack;
    fStack = new AliStack(1000);
    fFile->cd();
//  Connect treeE
    if (fTreeE) {
	delete fTreeE;
    } else {
	fTreeE = (TTree*)gDirectory->Get("TE");
    }

    if (fHeader) delete fHeader;
    fHeader = 0;
    fTreeE->SetBranchAddress("Header", &fHeader);
//  Get next event
    fTreeE->GetEntry(fNcurrent);
    fStack = fHeader->Stack();
    fStack->GetEvent(fNcurrent);

//  cd back to base file
    fBaseFile->cd();
//
    fNcurrent++;
    fNparticle = 0;
    Int_t ntrack =  fStack->GetNtrack();
    printf("\n Next event contains %d particles", ntrack);

    return  ntrack;
}

TParticle* AliGenReaderTreeK::NextParticle()
{
//  Return next particle
    TParticle* part = fStack->Particle(fNparticle);
    fNparticle++;
    return part;
}

AliGenReaderTreeK& AliGenReaderTreeK::operator=(const  AliGenReaderTreeK& rhs)
{
// Assignment operator
    return *this;
}

<commit_msg>Dummy copy constructor added.<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.2  2001/11/12 14:31:00  morsch
Memory leaks fixed. (M. Bondila)

Revision 1.1  2001/11/09 09:11:24  morsch
Realisation of AliGenReader that reads the kine tree (TreeK).

*/
#include <TFile.h>
#include <TTree.h>
#include <TParticle.h>

#include "AliGenReaderTreeK.h"
#include "AliStack.h"
#include "AliHeader.h"
#include "AliRun.h"

ClassImp(AliGenReaderTreeK);

AliGenReaderTreeK::AliGenReaderTreeK():AliGenReader()
{
//  Default constructor
    fFileName       = NULL;
    fStack          = 0;
    fHeader         = 0;
    fNcurrent       = 0;
    fNparticle      = 0;
    fFile           = 0;
    fBaseFile       = 0;
    fTreeE          = 0;
}

AliGenReaderTreeK::AliGenReaderTreeK(const AliGenReaderTreeK &reader)
{
    ;
}

AliGenReaderTreeK::~AliGenReaderTreeK()
{
// Destructor
    delete fTreeE;
}

void AliGenReaderTreeK::Init()
{
// Initialization
// Connect base file and file to read from

    TTree *ali = gAlice->TreeE();
    if (ali) {
	fBaseFile = ali->GetCurrentFile();
    } else {
	printf("\n Warning: Basefile cannot be found !\n");
    }
    fFile = new TFile(fFileName);
}

Int_t AliGenReaderTreeK::NextEvent()
{
// Read the next event
//  cd to file with old kine tree
    if (!fBaseFile) Init();
    if (fStack) delete fStack;
    fStack = new AliStack(1000);
    fFile->cd();
//  Connect treeE
    if (fTreeE) {
	delete fTreeE;
    } else {
	fTreeE = (TTree*)gDirectory->Get("TE");
    }

    if (fHeader) delete fHeader;
    fHeader = 0;
    fTreeE->SetBranchAddress("Header", &fHeader);
//  Get next event
    fTreeE->GetEntry(fNcurrent);
    fStack = fHeader->Stack();
    fStack->GetEvent(fNcurrent);

//  cd back to base file
    fBaseFile->cd();
//
    fNcurrent++;
    fNparticle = 0;
    Int_t ntrack =  fStack->GetNtrack();
    printf("\n Next event contains %d particles", ntrack);

    return  ntrack;
}

TParticle* AliGenReaderTreeK::NextParticle()
{
//  Return next particle
    TParticle* part = fStack->Particle(fNparticle);
    fNparticle++;
    return part;
}

AliGenReaderTreeK& AliGenReaderTreeK::operator=(const  AliGenReaderTreeK& rhs)
{
// Assignment operator
    return *this;
}

<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 —
            Vladimír Vondruš <mosra@centrum.cz>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Resource.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/GL/Renderer.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Math/Complex.h>
#include <Magnum/Math/Matrix3.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/Shaders/DistanceFieldVector.h>
#include <Magnum/Text/AbstractFont.h>
#include <Magnum/Text/DistanceFieldGlyphCache.h>
#include <Magnum/Text/Renderer.h>

namespace Magnum { namespace Examples {

using namespace Magnum::Math::Literals;

class TextExample: public Platform::Application {
    public:
        explicit TextExample(const Arguments& arguments);

    private:
        void viewportEvent(ViewportEvent& event) override;
        void drawEvent() override;
        void mouseScrollEvent(MouseScrollEvent& event) override;

        void updateText();

        PluginManager::Manager<Text::AbstractFont> _manager;
        Containers::Pointer<Text::AbstractFont> _font;

        Text::DistanceFieldGlyphCache _cache;
        GL::Mesh _text;
        GL::Buffer _vertices, _indices;
        Containers::Pointer<Text::Renderer2D> _text2;
        Shaders::DistanceFieldVector2D _shader;

        Matrix3 _transformation;
        Matrix3 _projection;
};

TextExample::TextExample(const Arguments& arguments): Platform::Application{arguments, Configuration{}.setTitle("Magnum Text Example")}, _cache(Vector2i(2048), Vector2i(512), 22), _text{NoCreate} {
    /* Load any TrueTypeFont plugin */
    _font = _manager.loadAndInstantiate("TrueTypeFont");
    if(!_font) std::exit(1);

    /* Open the font and fill glyph cache */
    Utility::Resource rs("fonts");
    if(!_font->openData(rs.getRaw("SourceSansPro-Regular.ttf"), 180.0f)) {
        Error() << "Cannot open font file";
        std::exit(1);
    }

    _font->fillGlyphCache(_cache, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:-+,.!°ěäЗдравстуймиΓειασουκόμ ");
    std::tie(_text, std::ignore) = Text::Renderer2D::render(*_font, _cache, 0.2f,
        "Hello, world!\n"
        "Ahoj, světe!\n"
        "Здравствуй, мир!\n"
        "Γεια σου κόσμε!\n"
        "Hej Världen!",
        _vertices, _indices, GL::BufferUsage::StaticDraw, Text::Alignment::MiddleCenter);

    _text2.reset(new Text::Renderer2D(*_font, _cache, 0.05f, Text::Alignment::TopRight));
    _text2->reserve(40, GL::BufferUsage::DynamicDraw, GL::BufferUsage::StaticDraw);

    GL::Renderer::enable(GL::Renderer::Feature::Blending);
    GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::SourceAlpha, GL::Renderer::BlendFunction::OneMinusSourceAlpha);
    GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add);

    _transformation = Matrix3::rotation(-10.0_degf);
    _projection = Matrix3::scaling(Vector2::yScale(Vector2(GL::defaultFramebuffer.viewport().size()).aspectRatio()));
    updateText();
}

void TextExample::viewportEvent(ViewportEvent& event) {
    GL::defaultFramebuffer.setViewport({{}, event.framebufferSize()});

    _projection = Matrix3::scaling(Vector2::yScale(Vector2(event.windowSize()).aspectRatio()));
}

void TextExample::drawEvent() {
    GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);

    _shader.bindVectorTexture(_cache.texture());

    _shader.setTransformationProjectionMatrix(_projection * _transformation)
        .setColor(Color3::fromHsv({216.0_degf, 0.85f, 1.0f}))
        .setOutlineColor(Color3{0.95f})
        .setOutlineRange(0.45f, 0.35f)
        .setSmoothness(0.025f/ _transformation.uniformScaling());
    _text.draw(_shader);

    _shader.setTransformationProjectionMatrix(_projection*
        Matrix3::translation(1.0f/ _projection.rotationScaling().diagonal()))
        .setColor(Color3{1.0f})
        .setOutlineRange(0.5f, 1.0f)
        .setSmoothness(0.075f);
    _text2->mesh().draw(_shader);

    swapBuffers();
}

void TextExample::mouseScrollEvent(MouseScrollEvent& event) {
    if(!event.offset().y()) return;

    if(event.offset().y() > 0)
        _transformation = Matrix3::rotation(1.0_degf)*Matrix3::scaling(Vector2(1.1f))* _transformation;
    else
        _transformation = Matrix3::rotation(-1.0_degf)*Matrix3::scaling(Vector2(1.0f/1.1f))* _transformation;

    updateText();

    event.setAccepted();
    redraw();
}

void TextExample::updateText() {
    _text2->render(Utility::formatString("Rotation: {:.2}°\nScale: {:.2}",
        Float(Deg(Complex::fromMatrix(_transformation.rotation()).angle())),
        _transformation.uniformScaling()));
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::TextExample)
<commit_msg>text: clean up and update.<commit_after>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 —
            Vladimír Vondruš <mosra@centrum.cz>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Resource.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/GL/Renderer.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Math/Complex.h>
#include <Magnum/Math/Matrix3.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/Shaders/DistanceFieldVector.h>
#include <Magnum/Text/AbstractFont.h>
#include <Magnum/Text/DistanceFieldGlyphCache.h>
#include <Magnum/Text/Renderer.h>

namespace Magnum { namespace Examples {

using namespace Math::Literals;

class TextExample: public Platform::Application {
    public:
        explicit TextExample(const Arguments& arguments);

    private:
        void viewportEvent(ViewportEvent& event) override;
        void drawEvent() override;
        void mouseScrollEvent(MouseScrollEvent& event) override;

        void updateText();

        PluginManager::Manager<Text::AbstractFont> _manager;
        Containers::Pointer<Text::AbstractFont> _font;

        Text::DistanceFieldGlyphCache _cache;
        GL::Mesh _rotatingText{NoCreate};
        GL::Buffer _vertices, _indices;
        Containers::Pointer<Text::Renderer2D> _dynamicText;
        Shaders::DistanceFieldVector2D _shader;

        Matrix3 _transformationRotatingText,
            _projectionRotatingText,
            _transformationProjectionDynamicText;
};

TextExample::TextExample(const Arguments& arguments):
    Platform::Application{arguments, Configuration{}
        .setTitle("Magnum Text Example")
        .setWindowFlags(Configuration::WindowFlag::Resizable)},
    _cache{Vector2i{2048}, Vector2i{512}, 22}
{
    /* Load a TrueTypeFont plugin and open the font */
    Utility::Resource rs("fonts");
    _font = _manager.loadAndInstantiate("TrueTypeFont");
    if(!_font || !_font->openData(rs.getRaw("SourceSansPro-Regular.ttf"), 180.0f))
        Fatal{} << "Cannot open font file";

    /* Glyphs we need to render everything */
    _font->fillGlyphCache(_cache,
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "0123456789:-+,.!°ěäЗдравстуймиΓειασουκόμ ");

    /* Text that rotates using mouse wheel. Size relative to the window size
       (1/10 of it) -- if you resize the window, it gets bigger */
    std::tie(_rotatingText, std::ignore) = Text::Renderer2D::render(*_font, _cache, 0.2f,
        "Hello, world!\n"
        "Ahoj, světe!\n"
        "Здравствуй, мир!\n"
        "Γεια σου κόσμε!\n"
        "Hej Världen!",
        _vertices, _indices, GL::BufferUsage::StaticDraw, Text::Alignment::MiddleCenter);
    _transformationRotatingText = Matrix3::rotation(-10.0_degf);
    _projectionRotatingText = Matrix3::projection(
        Vector2::xScale(Vector2{windowSize()}.aspectRatio()));

    /* Dynamically updated text that shows rotation/zoom of the other. Size in
       points that stays the same if you resize the window. Aligned so top
       right of the bounding box is at mesh origin, and then transformed so the
       origin is at the top right corner of the window. */
    _dynamicText.reset(new Text::Renderer2D(*_font, _cache, 32.0f, Text::Alignment::TopRight));
    _dynamicText->reserve(40, GL::BufferUsage::DynamicDraw, GL::BufferUsage::StaticDraw);
    _transformationProjectionDynamicText =
        Matrix3::projection(Vector2{windowSize()})*
        Matrix3::translation(Vector2{windowSize()}*0.5f);

    /* Set up premultiplied alpha blending to avoid overlapping text characters
       to cut into each other */
    GL::Renderer::enable(GL::Renderer::Feature::Blending);
    GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha);
    GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add);

    updateText();
}

void TextExample::viewportEvent(ViewportEvent& event) {
    GL::defaultFramebuffer.setViewport({{}, event.framebufferSize()});

    _projectionRotatingText = Matrix3::projection(
        Vector2::xScale(Vector2{windowSize()}.aspectRatio()));
    _transformationProjectionDynamicText =
        Matrix3::projection(Vector2{windowSize()})*
        Matrix3::translation(Vector2{windowSize()}*0.5f);
}

void TextExample::drawEvent() {
    GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);

    _shader.bindVectorTexture(_cache.texture());

    _shader
        .setTransformationProjectionMatrix(
            _projectionRotatingText*_transformationRotatingText)
        .setColor(0x2f83cc_rgbf)
        .setOutlineColor(0xdcdcdc_rgbf)
        .setOutlineRange(0.45f, 0.35f)
        .setSmoothness(0.025f/ _transformationRotatingText.uniformScaling());
    _rotatingText.draw(_shader);

    _shader
        .setTransformationProjectionMatrix(_transformationProjectionDynamicText)
        .setColor(0xffffff_rgbf)
        .setOutlineRange(0.5f, 1.0f)
        .setSmoothness(0.075f);
    _dynamicText->mesh().draw(_shader);

    swapBuffers();
}

void TextExample::mouseScrollEvent(MouseScrollEvent& event) {
    if(!event.offset().y()) return;

    if(event.offset().y() > 0)
        _transformationRotatingText = Matrix3::rotation(1.0_degf)*Matrix3::scaling(Vector2{1.1f})* _transformationRotatingText;
    else
        _transformationRotatingText = Matrix3::rotation(-1.0_degf)*Matrix3::scaling(Vector2{1.0f/1.1f})* _transformationRotatingText;

    updateText();

    event.setAccepted();
    redraw();
}

void TextExample::updateText() {
    _dynamicText->render(Utility::formatString("Rotation: {:.2}°\nScale: {:.2}",
        Float(Deg(Complex::fromMatrix(_transformationRotatingText.rotation()).angle())),
        _transformationRotatingText.uniformScaling()));
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::TextExample)
<|endoftext|>


<commit_before>// @(#)root/meta:$Id$
// Author: Rene Brun   13/11/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Global variables class (global variables are obtained from CINT).    //
// This class describes the attributes of a global variable.            //
// The TROOT class contains a list of all currently defined global      //
// variables (accessible via TROOT::GetListOfGlobals()).                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGlobal.h"
#include "TInterpreter.h"

ClassImp(TGlobal)

//______________________________________________________________________________
TGlobal::TGlobal(DataMemberInfo_t *info) : TDictionary(), fInfo(info)
{
   // Default TGlobal ctor. TGlobals are constructed in TROOT via
   // a call to TCint::UpdateListOfGlobals().

   if (fInfo) {
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal::TGlobal(const TGlobal &rhs) : TDictionary( ), fInfo(0)
{
   // Copy constructor

   if (rhs.fInfo) {
      fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal &TGlobal::operator=(const TGlobal &rhs)
{
   // Assignment operator.

   if (this != &rhs) {
      gCint->DataMemberInfo_Delete(fInfo);
      if (rhs.fInfo) {
         fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
         SetName(gCint->DataMemberInfo_Name(fInfo));
         SetTitle(gCint->DataMemberInfo_Title(fInfo));
      }
   }
   return *this;
}

//______________________________________________________________________________
TGlobal::~TGlobal()
{
   // TGlobal dtor deletes adopted CINT DataMemberInfo object.

   gCint->DataMemberInfo_Delete(fInfo);
}

//______________________________________________________________________________
void *TGlobal::GetAddress() const
{
   // Return address of global.

   return (void *)gCint->DataMemberInfo_Offset(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetArrayDim() const
{
   // Return number of array dimensions.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_ArrayDim(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetMaxIndex(Int_t dim) const
{
   // Return maximum index for array dimension "dim".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_MaxIndex(fInfo,dim);
}

//______________________________________________________________________________
const char *TGlobal::GetTypeName() const
{
   // Get type of global variable, e,g.: "class TDirectory*" -> "TDirectory".
   // Result needs to be used or copied immediately.

   if (!fInfo) return 0;
   return gCint->TypeName(gCint->DataMemberInfo_TypeName(fInfo));
}

//______________________________________________________________________________
const char *TGlobal::GetFullTypeName() const
{
   // Get full type description of global variable, e,g.: "class TDirectory*".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_TypeName(fInfo);
}

//______________________________________________________________________________
Long_t TGlobal::Property() const
{
   // Get property description word. For meaning of bits see EProperty.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_Property(fInfo);
}
<commit_msg>Undo test commit.<commit_after>// @(#)root/meta:$Id$
// Author: Rene Brun   13/11/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Global variables class (global variables are obtained from CINT).    //
// This class describes the attributes of a global variable.            //
// The TROOT class contains a list of all currently defined global      //
// variables (accessible via TROOT::GetListOfGlobals()).                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGlobal.h"
#include "TInterpreter.h"

ClassImp(TGlobal)

//______________________________________________________________________________
TGlobal::TGlobal(DataMemberInfo_t *info) : TDictionary(), fInfo(info)
{
   // Default TGlobal ctor. TGlobals are constructed in TROOT via
   // a call to TCint::UpdateListOfGlobals().

   if (fInfo) {
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal::TGlobal(const TGlobal &rhs) : TDictionary( ), fInfo(0)
{
   // Copy constructor

   if (rhs.fInfo) {
      fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal &TGlobal::operator=(const TGlobal &rhs)
{
   // Assignment operator.

   if (this != &rhs) {
      gCint->DataMemberInfo_Delete(fInfo);
      if (rhs.fInfo) {
         fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
         SetName(gCint->DataMemberInfo_Name(fInfo));
         SetTitle(gCint->DataMemberInfo_Title(fInfo));
      }
   }
   return *this;
}

//______________________________________________________________________________
TGlobal::~TGlobal()
{
   // TGlobal dtor deletes adopted CINT DataMemberInfo object.

   gCint->DataMemberInfo_Delete(fInfo);
}

//______________________________________________________________________________
void *TGlobal::GetAddress() const
{
   // Return address of global.

   return (void *)gCint->DataMemberInfo_Offset(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetArrayDim() const
{
   // Return number of array dimensions.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_ArrayDim(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetMaxIndex(Int_t dim) const
{
   // Return maximum index for array dimension "dim".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_MaxIndex(fInfo,dim);
}

//______________________________________________________________________________
const char *TGlobal::GetTypeName() const
{
   // Get type of global variable, e,g.: "class TDirectory*" -> "TDirectory".
   // Result needs to be used or copied immediately.

   if (!fInfo) return 0;
   return gCint->TypeName(gCint->DataMemberInfo_TypeName(fInfo));
}

//______________________________________________________________________________
const char *TGlobal::GetFullTypeName() const
{
   // Get full type description of global variable, e,g.: "class TDirectory*".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_TypeName(fInfo);
}

//______________________________________________________________________________
Long_t TGlobal::Property() const
{
   // Get property description word. For meaning of bits see EProperty.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_Property(fInfo);
}
<|endoftext|>


<commit_before>// @(#)root/meta:$Id$
// Author: Rene Brun   13/11/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Global variables class (global variables are obtained from CINT).    //
// This class describes the attributes of a global variable.            //
// The TROOT class contains a list of all currently defined global      //
// variables (accessible via TROOT::GetListOfGlobals()).                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGlobal.h"
#include "TInterpreter.h"

ClassImp(TGlobal)

//______________________________________________________________________________
TGlobal::TGlobal(DataMemberInfo_t *info) : TDictionary(), fInfo(info)
{
   // Default TGlobal ctor. TGlobals are constructed in TROOT via
   // a call to TCint::UpdateListOfGlobals().

   if (fInfo) {
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal::TGlobal(const TGlobal &rhs) : TDictionary( ), fInfo(0)
{
   // Copy constructor

   if (rhs.fInfo) {
      fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal &TGlobal::operator=(const TGlobal &rhs)
{
   // Assignment operator.

   if (this != &rhs) {
      gCint->DataMemberInfo_Delete(fInfo);
      if (rhs.fInfo) {
         fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
         SetName(gCint->DataMemberInfo_Name(fInfo));
         SetTitle(gCint->DataMemberInfo_Title(fInfo));
      }
   }
   return *this;
}

//______________________________________________________________________________
TGlobal::~TGlobal()
{
   // TGlobal dtor deletes adopted CINT DataMemberInfo object.

   gCint->DataMemberInfo_Delete(fInfo);
}

//______________________________________________________________________________
void *TGlobal::GetAddress() const
{
   // Return address of global.

   return (void *)gCint->DataMemberInfo_Offset(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetArrayDim() const
{
   // Return number of array dimensions.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_ArrayDim(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetMaxIndex(Int_t dim) const
{
   // Return maximum index for array dimension "dim".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_MaxIndex(fInfo,dim);
}

//______________________________________________________________________________
const char *TGlobal::GetTypeName() const
{
   // Get type of global variable, e,g.: "class TDirectory*" -> "TDirectory".
   // Result needs to be used or copied immediately.

   if (!fInfo) return 0;
   return gCint->TypeName(gCint->DataMemberInfo_TypeName(fInfo));
}

//______________________________________________________________________________
const char *TGlobal::GetFullTypeName() const
{
   // Get full type description of global variable, e,g.: "class TDirectory*".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_TypeName(fInfo);
}

//______________________________________________________________________________
Long_t TGlobal::Property() const
{
   // Get property description word. For meaning of bits see EProperty.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_Property(fInfo);
}
<commit_msg>Test commit.<commit_after>// @(#)root/meta:$Id$
// Author: Rene Brun   13/11/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Global variables class (global variables are obtained from CINT).    //
// This class describes the attributes of a global variable.            //
// The TROOT class contains a list of all currently defined global      //
// variables (accessible via TROOT::GetListOfGlobals()).                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGlobal.h"
#include "TInterpreter.h"

ClassImp(TGlobal)

//______________________________________________________________________________
TGlobal::TGlobal(DataMemberInfo_t *info) : TDictionary(), fInfo(info)
{
   // Default TGlobal ctor. TGlobals are constructed in TROOT via
   // a call to TCint::UpdateListOfGlobals().

   if (fInfo) {
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal::TGlobal(const TGlobal &rhs) : TDictionary( ), fInfo(0)
{
   // Copy constructor

   if (rhs.fInfo) {
      fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
      SetName(gCint->DataMemberInfo_Name(fInfo));
      SetTitle(gCint->DataMemberInfo_Title(fInfo));
   }
}

//______________________________________________________________________________
TGlobal &TGlobal::operator=(const TGlobal &rhs)
{
   // Assignment operator.

   if (this != &rhs) {
      gCint->DataMemberInfo_Delete(fInfo);
      if (rhs.fInfo) {
         fInfo = gCint->DataMemberInfo_FactoryCopy(rhs.fInfo);
         SetName(gCint->DataMemberInfo_Name(fInfo));
         SetTitle(gCint->DataMemberInfo_Title(fInfo));
      }
   }
   return *this;
}

//______________________________________________________________________________
TGlobal::~TGlobal()
{
   // TGlobal dtor deletes adopted CINT DataMemberInfo object.

   gCint->DataMemberInfo_Delete(fInfo);
}

//______________________________________________________________________________
void *TGlobal::GetAddress() const
{
   // Return address of global.

   return (void *)gCint->DataMemberInfo_Offset(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetArrayDim() const
{
   // Return number of array dimensions.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_ArrayDim(fInfo);
}

//______________________________________________________________________________
Int_t TGlobal::GetMaxIndex(Int_t dim) const
{
   // Return maximum index for array dimension "dim".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_MaxIndex(fInfo,dim);
}

//______________________________________________________________________________
const char *TGlobal::GetTypeName() const
{
   // Get type of global variable, e,g.: "class TDirectory*" -> "TDirectory".
   // Result needs to be used or copied immediately.

   if (!fInfo) return 0;
   return gCint->TypeName(gCint->DataMemberInfo_TypeName(fInfo));
}

//______________________________________________________________________________
const char *TGlobal::GetFullTypeName() const
{
   // Get full type description of global variable, e,g.: "class TDirectory*".

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_TypeName(fInfo);
}

//______________________________________________________________________________
Long_t TGlobal::Property() const
{
   // Get property description word. For meaning of bits see EProperty.

   if (!fInfo) return 0;
   return gCint->DataMemberInfo_Property(fInfo);
}
<|endoftext|>