static int run_test (int, char*[]) { // check the prescribed values of the required constants rw_fatal ('\0' == std::money_base::none, 0, 0, "'\\0' == money_base::none, got %d", std::money_base::none); rw_fatal ('\1' == std::money_base::space, 0, 0, "'\\1' == money_base::space, got %d", std::money_base::space); rw_fatal ('\2' == std::money_base::symbol, 0, 0, "'\\2' == money_base::symbol, got %d", std::money_base::symbol); rw_fatal ('\3' == std::money_base::sign, 0, 0, "'\\3' == money_base::sign, got %d", std::money_base::sign); rw_fatal ('\4' == std::money_base::value, 0, 0, "'\\4' == money_base::value, got %d", std::money_base::value); if (rw_enabled ("char")) { test_long_double (char (), "char"); test_string (char (), "char"); } else rw_note (0, __FILE__, __LINE__, "char test disabled"); #ifndef _RWSTD_NO_WCHAR_T if (rw_enabled ("wchar_t")) { test_long_double (wchar_t (), "wchar_t"); test_string (wchar_t (), "wchar_t"); } else rw_note (0, __FILE__, __LINE__, "wchar_t test disabled"); #endif // _RWSTD_NO_WCHAR_T return 0; }
static int run_test (int, char*[]) { // check that the number of loops is non-negative rw_fatal (-1 < rw_opt_nloops, 0, 0, "number of loops must be non-negative, got %d", rw_opt_nloops); const std::size_t N = std::size_t (rw_opt_nloops); test_fill (N); test_fill_n (N); return 0; }
void test_mismatch (const InputIterator &dummy, T*, const char *predicate) { // check that the number of loops is non-negative rw_fatal (-1 < rw_opt_nloops, 0, 0, "number of loops must be non-negative, got %d", rw_opt_nloops); const std::size_t N = std::size_t (rw_opt_nloops); if (rw_opt_no_input_iter) { rw_note (0, __FILE__, __LINE__, "InputIterator test disabled"); } else { test_mismatch (N, dummy, InputIter<UserClass>(0, 0, 0), (UserClass*)0, predicate); } if (rw_opt_no_fwd_iter) { rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled"); } else { test_mismatch (N, dummy, FwdIter<UserClass>(), (UserClass*)0, predicate); } if (rw_opt_no_bidir_iter) { rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled"); } else { test_mismatch (N, dummy, BidirIter<UserClass>(), (UserClass*)0, predicate); } if (rw_opt_no_rnd_iter) { rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled"); } else { test_mismatch (N, dummy, RandomAccessIter<UserClass>(), (UserClass*)0, predicate); } }
static int run_test (int, char**) { MyIos<char, std::char_traits<char> > nio; MyStreambuf<char, std::char_traits<char> > nsb; nio.rdbuf (&nsb); #ifndef _RWSTD_NO_WCHAR_T MyIos<wchar_t, std::char_traits<wchar_t> > wio; MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb; wio.rdbuf (&wsb); #endif // _RWSTD_NO_WCHAR_T // find all installed locales for which setlocale (LC_ALL) succeeds const char* const locale_list = rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL); const std::size_t maxinx = RW_COUNT_OF (locales); for (const char* name = locale_list; *name; name += std::strlen (name) + 1) { const std::size_t inx = nlocales; locales [inx] = name; // fill in the money and results for this locale MyMoneyData& data = my_money_data [inx]; data.locale_name_ = name; try { const std::locale loc (data.locale_name_); // initialize with random but valid values data.money_value_ = inx; data.type_ = MyMoneyData::PutId (nlocales % MyMoneyData::put_max); data.money_index_ = inx % RW_COUNT_OF (n_money_vals); // exercise domestic formats every other iteration // and international formats the rest data.intl_ = 0 == (inx & 1); // exercise postive and negative values if (inx & 1) data.money_value_ *= -1.; // add some random fractional digits if (inx & 2) data.money_value_ += data.money_value_ / 3.14; const std::money_put<char> &np = std::use_facet<std::money_put<char> >(loc); nio.imbue (loc); nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_)); switch (data.type_) { case MyMoneyData::put_ldbl: *np.put (std::ostreambuf_iterator<char>(&nsb), data.intl_, nio, ' ', data.money_value_) = '\0'; break; case MyMoneyData::put_string: *np.put (std::ostreambuf_iterator<char>(&nsb), data.intl_, nio, ' ', n_money_vals [data.money_index_]) = '\0'; break; case MyMoneyData::put_max: // avoid enumeration value `put_max' not handled in switch // this case should never happen break; } rw_assert (!nio.fail (), __FILE__, __LINE__, "money_put<char>::put(...) " "failed for locale(%#s)", data.locale_name_); #ifndef _RWSTD_NO_WCHAR_T const std::money_put<wchar_t> &wp = std::use_facet<std::money_put<wchar_t> >(loc); wio.imbue (loc); wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_)); switch (data.type_) { case MyMoneyData::put_ldbl: *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb), data.intl_, wio, L' ', data.money_value_) = '\0'; break; case MyMoneyData::put_string: *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb), data.intl_, wio, L' ', w_money_vals [data.money_index_]) = L'\0'; break; case MyMoneyData::put_max: // avoid enumeration value `put_max' not handled in switch // this case should never happen break; } rw_assert (!nio.fail (), __FILE__, __LINE__, "money_put<wchar_t>::put(...) " "failed for locale(%#s)", data.locale_name_); #endif // _RWSTD_NO_WCHAR_T if (opt_shared_locale) data.locale_ = loc; nlocales += 1; } catch (...) { rw_warn (!rw_opt_locales, 0, __LINE__, "failed to create locale(%#s)", name); } if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales)) break; } // avoid divide by zero in thread if there are no locales to test rw_fatal (nlocales != 0, 0, __LINE__, "failed to create one or more usable locales!"); rw_info (0, 0, 0, "testing std::money_put<charT> with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::money_put<char>"); test_char = true; test_wchar = false; // create and start a pool of threads and wait for them to finish int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T rw_info (0, 0, 0, "exercising std::money_put<wchar_t>"); test_char = false; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time rw_info (0, 0, 0, "exercising both std::money_put<char> " "and std::money_put<wchar_t>"); test_char = true; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T return result; }
static int run_test (int, char**) { MyIos<char, std::char_traits<char> > nio; MyStreambuf<char, std::char_traits<char> > nsb; nio.rdbuf (&nsb); #ifndef _RWSTD_NO_WCHAR_T MyIos<wchar_t, std::char_traits<wchar_t> > wio; MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb; wio.rdbuf (&wsb); #endif // _RWSTD_NO_WCHAR_T // find all installed locales for which setlocale(LC_ALL) succeeds const char* const locale_list = rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL); const std::size_t maxinx = RW_COUNT_OF (locales); for (const char *name = locale_list; *name; name += std::strlen (name) + 1) { const std::size_t inx = nlocales; locales [inx] = name; // fill in the value and results for this locale MyNumData& data = my_num_data [nlocales]; data.locale_name_ = name; try { const std::locale loc (data.locale_name_); data.value_ = nlocales & 1 ? -1 * nlocales : nlocales; data.type_ = MyNumData::PutId (nlocales % MyNumData::put_max); // format data into buffers const std::num_put<char> &np = std::use_facet<std::num_put<char> >(loc); nio.imbue (loc); nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_)); put_data (data, np, std::ostreambuf_iterator<char>(&nsb), nio, ' ', '\0'); rw_fatal (!nio.fail (), __FILE__, __LINE__, "num_put<char>::put(...) failed for locale(%#s)", data.locale_name_); #ifndef _RWSTD_NO_WCHAR_T const std::num_put<wchar_t> &wp = std::use_facet<std::num_put<wchar_t> >(loc); wio.imbue (loc); wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_)); put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb), wio, L' ', L'\0'); rw_fatal (!wio.fail (), __FILE__, __LINE__, "num_put<wchar_t>::put(...) failed for locale(%#s)", data.locale_name_); #endif // _RWSTD_NO_WCHAR_T if (opt_shared_locale) data.locale_ = loc; nlocales += 1; } catch (...) { rw_warn (!rw_opt_locales, 0, __LINE__, "failed to create locale(%#s)", name); } if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales)) break; } // avoid divide by zero in thread if there are no locales to test rw_fatal (nlocales != 0, 0, __LINE__, "failed to create one or more usable locales!"); rw_info (0, 0, 0, "testing std::num_put<charT> with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::num_put<char>"); test_char = true; test_wchar = false; // create and start a pool of threads and wait for them to finish int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T rw_info (0, 0, 0, "exercising std::num_put<wchar_t>"); test_char = false; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time rw_info (0, 0, 0, "exercising both std::num_put<char> and std::num_put<wchar_t>"); test_char = true; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T return result; }
static int run_test (int, char**) { // find all installed locales for which setlocale(LC_ALL) succeeds const char* const locale_list = rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL); // array of locale names to use for testing const char* locales [sizeof punct_data / sizeof *punct_data]; const std::size_t maxinx = sizeof locales / sizeof *locales; // iterate over locales, initializing a global punct_data array for (const char *name = locale_list; *name; name += std::strlen (name) +1) { std::locale loc; MoneypunctData* const pdata = punct_data + nlocales; pdata->locale_name_ = name; locales [nlocales] = name; try { loc = std::locale (name); typedef std::moneypunct<char, false> Punct; const Punct &mp = std::use_facet<Punct>(loc); const char dp = mp.decimal_point (); const char ts = mp.thousands_sep (); const std::string grp = mp.grouping (); const std::string cur = mp.curr_symbol (); const std::string pos = mp.positive_sign (); const std::string neg = mp.negative_sign (); const int fd = mp.frac_digits (); const Punct::pattern pfm = mp.pos_format (); const Punct::pattern nfm = mp.neg_format (); pdata->decimal_point_ = dp; pdata->thousands_sep_ = ts; pdata->frac_digits_ = fd; std::strcpy (pdata->grouping_, grp.c_str ()); std::strcpy (pdata->curr_symbol_, cur.c_str ()); std::strcpy (pdata->positive_sign_, pos.c_str ()); std::strcpy (pdata->negative_sign_, neg.c_str ()); std::memcpy (pdata->pos_format_, &pfm, sizeof pfm); std::memcpy (pdata->neg_format_, &nfm, sizeof nfm); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } try { typedef std::moneypunct<char, true> Punct; const Punct &mp = std::use_facet<Punct>(loc); const std::string cur = mp.curr_symbol (); const int fd = mp.frac_digits (); const Punct::pattern pfm = mp.pos_format (); const Punct::pattern nfm = mp.neg_format (); pdata->int_frac_digits_ = fd; std::strcpy (pdata->int_curr_symbol_, cur.c_str ()); std::memcpy (pdata->int_pos_format_, &pfm, sizeof pfm); std::memcpy (pdata->int_neg_format_, &nfm, sizeof nfm); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } #ifndef _RWSTD_NO_WCHAR_T try { typedef std::moneypunct<wchar_t, false> Punct; const Punct &mp = std::use_facet<Punct>(loc); const wchar_t dp = mp.decimal_point (); const wchar_t ts = mp.thousands_sep (); const std::wstring cur = mp.curr_symbol (); const std::wstring pos = mp.positive_sign (); const std::wstring neg = mp.negative_sign (); pdata->wdecimal_point_ = dp; pdata->wthousands_sep_ = ts; typedef std::wstring::traits_type Traits; Traits::copy (pdata->wcurr_symbol_, cur.data (), cur.size ()); Traits::copy (pdata->wpositive_sign_, pos.data (), pos.size ()); Traits::copy (pdata->wnegative_sign_, neg.data (), neg.size ()); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } try { typedef std::moneypunct<wchar_t, true> Punct; const Punct &mp = std::use_facet<Punct>(loc); const std::wstring cur = mp.curr_symbol (); const std::wstring pos = mp.positive_sign (); const std::wstring neg = mp.negative_sign (); typedef std::wstring::traits_type Traits; Traits::copy (pdata->wint_curr_symbol_, cur.data (), cur.size ()); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } #endif // _RWSTD_NO_WCHAR_T ++nlocales; if (nlocales == maxinx) break; } // unless the number of iterations was explicitly specified // on the command line, decrease the number to equal the number // of excericsed locales when only one thread is being tested if (1 == opt_nthreads && opt_nloops < 0) opt_nloops = int (nlocales); // when the number of iterations wasn't explicitly specified // on the command line set it to the default value if (opt_nloops < 0) opt_nloops = DFLT_LOOPS; rw_fatal (0 < nlocales, 0, __LINE__, "must have at least one valid locale to test"); rw_info (0, 0, 0, "testing std::moneypunct<charT> with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::moneypunct<char>"); test_char = true; test_wchar = false; // create and start a pool of threads and wait for them to finish int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T rw_info (0, 0, 0, "exercising std::moneypunct<wchar_t>"); test_char = false; test_wchar = true; // start a pool of threads to exercise the thread safety // of the wchar_t specialization result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time rw_info (0, 0, 0, "exercising both std::moneypunct<char> " "and std::moneypunct<wchar_t>"); test_char = true; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T return result; }
static int run_test (int, char**) { // find all installed locales for which setlocale(LC_ALL) succeeds const char* const locale_list = rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL); const std::size_t maxinx = sizeof punct_data / sizeof *punct_data; // iterate over locales, initializing a global punct_data array for (const char *name = locale_list; *name; name += std::strlen (name) +1) { const std::size_t inx = nlocales; locales [inx] = name; NumPunctData& data = punct_data [inx]; try { std::locale loc(name); data.locale_name_ = name; const std::numpunct<char> &np = std::use_facet<std::numpunct<char> >(loc); data.grouping_ = np.grouping (); data.decimal_point_ = np.decimal_point (); data.thousands_sep_ = np.thousands_sep (); data.truename_ = np.truename (); data.falsename_ = np.falsename (); #ifndef _RWSTD_NO_WCHAR_T const std::numpunct<wchar_t> &wp = std::use_facet<std::numpunct<wchar_t> >(loc); data.wdecimal_point_ = wp.decimal_point (); data.wthousands_sep_ = wp.thousands_sep (); data.wtruename_ = wp.truename (); data.wfalsename_ = wp.falsename (); #endif if (opt_shared_locale) data.locale_ = loc; nlocales += 1; } catch (...) { rw_warn (!rw_opt_locales, 0, __LINE__, "failed to create locale(%#s)", name); } if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales)) break; } // avoid divide by zero in thread if there are no locales to test rw_fatal (nlocales != 0, 0, __LINE__, "failed to create one or more usable locales!"); rw_info (0, 0, 0, "testing std::numpunct<charT> with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::numpunct<char>"); test_char = true; test_wchar = false; // create and start a pool of threads and wait for them to finish int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T rw_info (0, 0, 0, "exercising std::numpunct<wchar_t>"); test_char = false; test_wchar = true; // start a pool of threads to exercise the thread safety // of the wchar_t specialization result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time rw_info (0, 0, 0, "exercising both std::numpunct<char> and std::numpunct<wchar_t>"); test_char = true; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T return result; }
void run_test (intT, thr_args_base::tag_t tag) { static const char* const tname = rw_any_t (intT ()).type_name (); if (!rw_enabled (tname)) { rw_note (0, 0, 0, "%s test disabled", tname); return; } #ifdef _RWSTD_REENTRANT static const char* const fun = "__rw_atomic_exchange"; rw_info (0, 0, 0, "__rw::%s (%s&, %2$s): %d iterations in %d threads", fun, tname, rw_opt_nloops, rw_opt_nthreads); rw_thread_t tid [MAX_THREADS]; typedef thr_args<intT> Args; Args::nthreads_ = unsigned (rw_opt_nthreads); Args::type_tag_ = tag; Args::nincr_ = unsigned (rw_opt_nloops); Args::shared_ [0] = intT (1); Args::shared_ [1] = intT (1); _RWSTD_ASSERT (Args::nthreads_ < sizeof tid / sizeof *tid); Args args [sizeof tid / sizeof *tid]; for (unsigned long i = 0; i != Args::nthreads_; ++i) { args [i].threadno_ = i; args [i].niter_ = 0; args [i].nxchg_ = 0; rw_fatal (0 == rw_thread_create (tid + i, 0, thread_routine, args + i), 0, __LINE__, "thread_create() failed"); } for (unsigned long i = 0; i != Args::nthreads_; ++i) { rw_error (0 == rw_thread_join (tid [i], 0), 0, __LINE__, "thread_join() failed"); if (args [i].niter_) { // compute the percantage of thread iterations that resulted // in increments of one of the shared variables const unsigned long incrpcnt = (100U * Args::nincr_) / args [i].niter_; printf ("thread %lu performed %lu exchanges in %lu iterations " "(%lu%% increments)\n", args [i].threadno_, args [i].nxchg_, args [i].niter_, incrpcnt); } } // compute the expected result, "skipping" zeros by incrementing // expect twice when it overflows and wraps around to 0 (zero is // used as the lock variable in thread_routine() above) intT expect = intT (1); const unsigned long nincr = (Args::nthreads_ * Args::nincr_) / 2U; for (unsigned long i = 0; i != nincr; ++i) { if (intT () == ++expect) ++expect; } // verify that the final value of the variables shared among all // threads equals the number of increments performed by the threads rw_assert (Args::shared_ [0] == expect, 0, __LINE__, "1. %s (%s&, %2$s); %s == %s failed", fun, tname, TOSTR (Args::shared_ [0]), TOSTR (expect)); rw_assert (Args::shared_ [1] == expect, 0, __LINE__, "2. %s (%s&, %2$s); %s == %s failed", fun, tname, TOSTR (Args::shared_ [1]), TOSTR (expect)); #else // if !defined (_RWSTD_REENTRANT) _RWSTD_UNUSED (tag); #endif // _RWSTD_REENTRANT }