Comparator case insensitive string set - c++

I was just checking effective STL(book) example for set comparator to implement case insensitive set, but i am facing problems(visual studio says comaparator not valid but it worked in ideone). I am sure there is something wrong in my implementation even then it is little confusing what is right.
Below is the code
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
using namespace std;
inline int ciCharCompare(char c1, char c2) // case-insensitively compare chars
{ // c1 and c2, returning -1 if c1 < c2,
//0 if c1==c2, and 1 if c1 > c2
int Ic1 = tolower(static_cast<unsigned char>(c1)); //see below for
int Ic2 = tolower(static_cast<unsigned char>(c2)); // info on these
if (Ic1 < Ic2) return -1;
if (Ic1 > Ic2) return 1;
return 0;
}
struct CiStringCompare : public std::binary_function<string, string, bool>
{
int ciStringCompareImpl(const string& s1, const string& s2) const
{
auto p = mismatch( //see below for an
s1.begin(), s1.end(), //explanation of why
s2.begin(), //we need not2;see
not2(ptr_fun(ciCharCompare))); //Item 41 for why we
// need ptr_fun
if (p.first == s1.end()) { //if true, either s1 and
if (p.second == s2.end()) return 0; // s2 are equal or
else return -1; //s1 is shorter than s2
}
return ciCharCompare(*p.first, *p.second);
}
int xxxx(const string& s1, const string& s2) const
{
if (s1.size() <= s2.size()) return ciStringCompareImpl(s1, s2);
else return -ciStringCompareImpl(s2, s1);
}
int operator()(const string& str1, const string& str2) const {
return xxxx(str1, str2);
}
};
class DifferenceBetweenEquivalenceandEquality
{
// Comparator functor
set<string, CiStringCompare> s;
public:
DifferenceBetweenEquivalenceandEquality(const vector<string>& v)
{
for (const auto& x : v)
s.insert(x);
}
void print() {
for(const auto& x: s)
cout << x << endl;
}
};
int main()
{
DifferenceBetweenEquivalenceandEquality dbee({ "STL","stl","aaa","bbb" });
dbee.print();
return 0;
}
It is working fine in ideone though, so im confused as to what makes a comparator valid and how the equality, equivalence and ordering effect by each of these
For example :: In normal set i get
STL stl aaa bbb
but using the below comparator i get
aaa bbb stl STL
inline string toLowerCase(const string& str) {
string res(str);
int i;
for (i = 0; i < (int)res.size(); i++)
res[i] = (char)tolower(res[i]);
return res;
}
class NormalComparator
{
public:
bool operator()(const string& s1, const string& s2)
{
return toLowerCase(s1) < toLowerCase(s2) ||
!(toLowerCase(s2) < toLowerCase(s1)) && s1 < s2;
}
};

Related

std::map<struct,struct>::find is not finding a match, but if i loop thru begin() to end() i see the match right there

struct chainout {
LONG cl;
std::string cs;
bool operator<(const chainout&o)const {
return cl < o.cl || cs < o.cs;
}
} ;
struct chainin{
std::string tm;
std::string tdi;
short mss;
LONG pinid;
bool operator<(const chainin&o)const {
return mss < o.mss || pinid < o.pinid || tm<o.tm; //no tdi right now it's always empty
}
};
std::map <chainin,chainout> chainmap;
std::map<chainin,chainout>::iterator it;
chainin ci;
chainout co;
string FADEDevicePinInfo::getNetAtPinIdTmTidMss (const LONG p,const string tm, const string tid,const LONG mss){
ci.tm=tm;
// ci.tdi=tid;
ci.tdi="";
ci.mss=(short)mss;
ci.pinid=p;
for (it=chainmap.begin();it!=chainmap.end();it++){
if(it->first.pinid==ci.pinid && it->first.tm==ci.tm&&it->first.mss==ci.mss && it->first.tdi==ci.tdi){
cout << "BDEBUG: found p["; cout<<it->first.pinid; cout<<"] tm["; cout<<it->first.tm.c_str();cout<<"] mss[";cout<<it->first.mss;cout<<"] : ";cout<<it->second.chainSignal.c_str();cout<<endl;
}
}
it=chainmap.find(ci);
if(it == chainmap.end()){
MSG(SEV_T,("no pin data found for pin[%ld]/tm[%s]/tdi[%s]/mss[%ld]",ci.pinid,ci.tm.c_str(),ci.tdi.c_str(),ci.mss));
}
return it->second.cs;
}
This is both printing the successfully found line, and then throwing the sev_t error due to map::find not returning a match. what did i do wrong?
I added print statements thruout the < function, but it seems to be ordering the map correctly, and when i do the lookup, it seems to find the correct mss/pinid, but then only sees one tm, which is the wrong tm.
As noted in comments, you have a bad comparison operator. If you don't know what order the objects should be sorted in, then neither does std::map or any other sorted container.
When you have multiple things to compare, consider deciding which is most important, and use std::tie to compare them, as demonstrated here:
#include <string>
#include <iostream>
struct chainout {
int cl;
std::string cs;
bool operator<(const chainout&o)const {
return std::tie(cl, cs) < std::tie(o.cl, o.cs);
}
};
int main(){
chainout a{ 1, "b" };
chainout b{ 2, "a" };
std::cout << (a < b) << std::endl;
std::cout << (b < a) << std::endl;
}
The operator< for both of your structs are implemented incorrectly.
std::map requires key comparisons to use Strict Weak Ordering. That means when your structs want to compare multiple fields, they need to compare later fields only when earlier fields compare equal. But you are not checking for that condition. You are returning true if any field in one instance compares less-than the corresponding field in the other instance, regardless of the equality (or lack of) in the other fields. So you are breaking SWO, which causes undefined behavior in std::map's lookups.
Try this instead:
struct chainout {
LONG cl;
std::string cs;
bool operator<(const chainout &o) const {
/*
if (cl < o.cl) return true;
if (cl == o.cl) return (cs < o.cs);
return false;
*/
return (cl < o.cl) || ((cl == o.cl) && (cs < o.cs));
}
};
struct chainin{
std::string tm;
std::string tdi;
short mss;
LONG pinid;
bool operator<(const chainin &o) const {
if (mss < o.mss) return true;
if (mss == o.mss) {
if (pinid < o.pinid) return true;
if (pinid == o.pinid) return (tm < o.tm);
}
return false;
}
};
An easier way to implement this is to use std::tie() instead, which has its own operator< to handle this for you, eg:
struct chainout {
LONG cl;
std::string cs;
bool operator<(const chainout &o) const {
return std::tie(cl, cs) < std::tie(o.cl, o.cs);
}
};
struct chainin{
std::string tm;
std::string tdi;
short mss;
LONG pinid;
bool operator<(const chainin &o) const {
return std::tie(mss, pinid, tm) < std::tie(o.mss, o.pinid, o.tm);
}
};
Either way, then std::map::find() should work as expected, eg:
std::map<chainin, chainout> chainmap;
string FADEDevicePinInfo::getNetAtPinIdTmTidMss (const LONG p, const string tm, const string tid, const LONG mss)
{
chainin ci;
ci.tm = tm;
//ci.tdi = tid;
ci.tdi = "";
ci.mss = (short) mss;
ci.pinid = p;
std::map<chainin, chainout>::iterator it = chainmap.find(ci);
if (it != chainmap.end()) {
cout << "BDEBUG: found"
<< " p[" << it->first.pinid << "]"
<< " tm[" << it->first.tm << "]"
<< " mss[" << it->first.mss << "]"
<< " : " << it->second.cs
<< endl;
}
}

Merge two std::sets

I need to merge two sets into a resultant set on basis of one member variable qty if the prices are same. In the below example my resultant set s3 should contain:
Price : 100
Qty : 40
Price : 200
Qty : 60
Please note qty above is a sum of qty in both the sets respective when the price is same.
My question is how do I construct the set s3 below:
Please guide me with the same.
#include <set>
#include <iostream>
using namespace std;
class PriceLevel
{
public:
int price;
int qty;
PriceLevel(int _price, int _qty)
{
price = _price;
qty = _qty;
}
friend bool operator<(const PriceLevel &p, const PriceLevel &q);
};
bool operator<(const PriceLevel &p, const PriceLevel &q)
{
if(p.price < q.price)
{
return true;
}
else
{
return false;
}
}
int main()
{
std::set<PriceLevel> s1;
std::set<PriceLevel> s2;
PriceLevel p1(100,10);
PriceLevel p2(200,20);
PriceLevel p3(100,30);
PriceLevel p4(200,40);
s1.insert(p1);
s1.insert(p2);
s2.insert(p3);
s2.insert(p4);
std::set<PriceLevel> s3;
set<PriceLevel>::iterator it = s3.begin();
// How should I Initialize s3
for(; it != s3.end(); it++)
{
cout << "Price: " << it->price << endl;
cout << "Qty : " << it->qty << endl;
}
}
If you are absolutely sure that both source sets contain exactly the same prices, you can use the binary version of std::transform.
If they might contain unequal data, you'll have to do it manually, like this:
std::set<PriceLevel> s3;
// How should I Initialize s3
std::set<PriceLevel>::iterator
first1 = s1.begin(),
last1 = s1.end(),
first2 = s2.begin(),
last2 = s2.end();
while (first1 != last1 && first2 != last2) {
if (first1->price < first2->price) {
s3.insert(*first1++);
}
else if (first1->price > first2->price) {
s3.insert(*first2++);
}
else {
s3.insert(PriceLevel(first1->price, first1->qty + first2->qty));
++first1;
++first2;
}
}
while (first1 != last1) {
s3.insert(*first1++);
}
while (first2 != last2) {
s3.insert(*first2++);
}
This is best put in an extra function.
View on IdeOne
If you only need those prices in the result set which existed in both source sets, it is a bit simpler:
while (first1 != last1 && first2 != last2) {
if (first1->price < first2->price) {
++first1;
}
else if (first1->price > first2->price) {
++first2;
}
else {
s3.insert(PriceLevel(first1->price, first1->qty + first2->qty));
++first1;
++first2;
}
}
You can merge two sets with just two lines
#include <set>
template <typename _Ty>
std::set<_Ty> merge(const std::set<_Ty> &x, const std::set<_Ty> &y) const
{
std::set<_Ty> merged = x; //initial merged set from x
merged.insert(y.begin(), y.end()); //add contents of y to merged
return move(merged);
}
set is not an appropriate data structure for your application here. Consider using a map<int, int> instead:
map<int, int> p1, p2, p3; // map price -> quantity
p1[100] = 10;
p1[200] = 20;
p2[100] = 30;
p2[200] = 40;
p3 = p1;
for(auto &i : p2) {
p3[i.first] += i.second;
}
// Now p3[100]=40 and p3[200]=60.
You can also use a set kind of like a map using set::find:
s3 = s1;
for(auto &i : s2) {
auto it = s3.find(i);
if(it == s3.end()) {
s3.insert(i);
} else {
it->qty += i.qty;
}
}
For this to work, you will have to declare qty as a mutable int, so that it can be modified even if the PriceLevel struct is const (since elements of a set are const).
If you can't make the variable mutable, then you can try removing the existing set element and then adding a new, merged element.
You are essentially trying to use a set as a map AND merge values with equal keys. You will need to roll your own result (not to mention that it really isn't advisable...). Here is something to get you started.
#include <iostream>
#include <set>
using namespace std;
class PriceLevel
{
public:
int price;
int qty;
PriceLevel() {
price = 0;
qty = 0;
}
PriceLevel(int _price, int _qty)
{
price = _price;
qty = _qty;
}
friend bool operator<(const PriceLevel &p, const PriceLevel &q);
//Compares two PriceLevel objects and merges their values if their keys are the same.
//Return value is a std::pair that
//denotes if the compare was successful and the result is meaningful.
static std::pair<bool, PriceLevel> merge_equal(const PriceLevel& p, const PriceLevel& q) {
std::pair<bool, PriceLevel> result;
result.first = false;
if(p.price == q.price) {
result.first = true;
result.second.price = p.price;
result.second.qty = p.qty + q.qty;
}
return result;
}
};
bool operator<(const PriceLevel &p, const PriceLevel &q)
{
if(p.price < q.price)
{
return true;
}
else
{
return false;
}
}
int main()
{
std::set<PriceLevel> s1;
std::set<PriceLevel> s2;
PriceLevel p1(100,10);
PriceLevel p2(200,20);
PriceLevel p3(100,30);
PriceLevel p4(200,40);
s1.insert(p1);
s1.insert(p2);
s2.insert(p3);
s2.insert(p4);
std::set<PriceLevel> s3;
//Just in case...the world may explode otherwise.
if(s1.size() == s2.size()) {
for(const auto& pl1 : s1) {
for(const auto& pl2 : s2) {
//Only insert valid values.
auto r = PriceLevel::merge_equal(pl1, pl2);
if(r.first) s3.insert(r.second);
}
}
for(auto it = s3.begin(); it != s3.end(); it++) {
cout << "Price: " << it->price << endl;
cout << "Qty : " << it->qty << endl;
}
}
}

Is there a built in function for std::string in C++ to compare two strings alphabetically when either string can be uppercase or lowercase?

I know for C++ that basic comparative operators can accomplish the task if both words are either entirely lower or entirely upper case. I have an array of strings and letters can vary from lower to upper. Here is a small examle of the kind of strings I can be working with:
"ABUNDANT LIFE CH"
"NEW LIFE WMN MNSTRY"
"NEW LIFE ASSEMBLY"
I know in Java there exists the function String.compareToIgnoreCase(). Is there a C++ equivalent of this function?
I don't know of any case-insensitive functions in the standard library, but you can specify a custom predicate for std::equal:
std::string a("hello");
std::string b("HELLO");
std::cout << std::equal(a.begin(), a.end(), b.begin(),
[] (const char& a, const char& b)
{
return (std::tolower(a) == std::tolower(b));
});
For a solution which takes locale into account, refer to Case insensitive std::string.find().
#include <locale>
template<typename charT = std::string::value_type>
struct my_equal {
my_equal( const std::locale& loc ) : loc_(loc) {}
bool operator()(charT ch1, charT ch2) {
return std::toupper(ch1, loc_) == std::toupper(ch2, loc_);
}
private:
const std::locale& loc_;
};
int main()
{
std::string a("hello");
std::string b("HELLO");
std::cout << std::equal(a.begin(), a.end(), b.begin(),
my_equal<>(std::locale()));
}
Yes there is a case insensitive way to compare strings in C++. The key is that std::string is a template:
template <class charT,
class traits = char_traits<charT>,
class Allocator = allocator<charT>>
class basic_string;
The traits here control how the charT's relate to each other. For normal std::string, they do what you'd expect, but we can just write our own traits that are case insensitive:
struct case_insensitive_traits
: char_traits<char>
{
static bool eq(char a, char b) { return tolower(a) == tolower(b); }
static bool ne(char a, char b) { return !eq(a, b); }
static bool lt(char a, char b) { return tolower(a) < tolower(b); }
static bool gt(char a, char b) { return tolower(a) > tolower(b); }
static int compare(const char* a, const char* b, size_t n)
{
for (size_t i = 0; i < n; ++i) {
int delta = tolower(a[i]) - tolower(b[i]);
if (delta != 0) return delta;
}
return 0;
}
static const char* find(const char* s, size_t n, char c)
{
c = tolower(c);
for (size_t i = 0; i < n; ++i, ++s) {
if (tolower(*s) == c) return s;
}
return nullptr;
}
};
With that:
using case_insensitive_string = std::basic_string<char, case_insensitive_traits>;
case_insensitive_string a{"hello"};
case_insensitive_string b{"hElLo"};
assert(a == b);
You can use Boost String Algorithms:
#include <string>
#include <cassert>
#include <boost/algorithm/string.hpp>
int main() {
std::string s { "Test" };
assert(boost::iequals(s, "TEST"));
}
In C++ usually less-than (bool less(type, type)) is used in places of tri-value function compare (int cmp(type, type)). Of course each one of them can be trivially defined in terms of the other.
Here's something that can easily be plugged into STL algorithms:
template<class String>
struct ciless {
locale l_;
explicit ciless(locale l = locale()) : l_(l) {}
bool operator() (
String const &a
, String const &b) const
{
auto fa = a.begin();
auto fb = b.begin();
while (fa != a.end()
&& fb != b.end()
&& (tolower(*fa, l_) == tolower(*fb, l_)))
{
++fa;
++fb;
}
return
(fa == a.end() && fb != b.end())
|| (
fa != a.end()
&& fb != b.end()
&& tolower(*fa, l_) < tolower(*fb, l_));
}
};
And here's something that can convert less() into java-style compare():
template<class T, class Less = std::less<T>>
struct compare
{
Less l_;
explicit compare(Less l = Less()) : l_(l) {}
int operator() (
T const &a
, T const &b) const
{
if (l_(a, b))
return -1;
if (l_(b, a))
return 1;
return 0;
}
};
Nothing standard, but if you happen to be developing for Windows or have access to a Posix interface you could use the following:
https://msdn.microsoft.com/en-us/library/k59z8dwe.aspx
// didn't run it through a compiler
// but it would look like something like this:
{
using namespace std;
string a = "HELLO"s;
string b = "HelLO"s;
bool bIsMatch = _stricmp(a.c_str(), b.c_str()) == 0; // bIsMatch = true
}
There's a much simpler solution that doesn't involve coding loops (ugh!) or Boost:
string a = "Foo";
string b = "foo"
return !_stricmp(a.str(), b.str());
The strings are converted to char[]s, then compared, case-insensitive. Returns true if they're equal.
(My biased opinion: C++ should provide this functionality as a string method. Forcing millions of users to hand-code loops for such a common operation is disgusting, and introduces unnecessary "noise" into the code.)

Code review, C++, Anagram method

I'm doing some practice questions from the book "Cracking the coding interview" and wanted to get some people to review my code for bugs and optimizations. Any feedback would be greatly appreciated.
Question: Write a method to decide if two strings are anagrams or not.
/*
Time complexity: O(n^2)
Space complexity: O(n)
*/
bool IsAnagram(std::string str1, std::string str2)
{
if(str1.length() != str2.length())
return false;
for(int i = 0; i < str1.length();i++)
{
bool found = false;
int j = 0;
while(!found && j < str2.length())
{
if(str1[i] == str2[j])
{
found = true;
str2[j] = NULL;
}
j++;
}
if(!found)
return false;
}
return true;
}
This is more efficient generally
#include <iostream>
#include <string>
#include <algorithm>
bool IsAnagram(std::string& str1, std::string& str2)
{
if(str1.length() != str2.length())
return false;
std::sort(str1.begin(), str1.end());
std::sort(str2.begin(), str2.end());
return str1.compare(str2) == 0;
}
int main(int argc, char* argv[])
{
std::string an1("army");
std::string an2("mary");
if(IsAnagram(an1, an2))
std::cout << "Hooray!\n";
return 0;
}
For those who dislike the mutating strings then maybe this is a better option. Could either remove reference to parameters 1 and 2 or make a copy inside function as here. This way, parameters can be const.
bool IsAnagram2(const std::string& str1, const std::string& str2)
{
if(str1.length() != str2.length())
return false;
std::string cpy1(str1), cpy2(str2);
std::sort(cpy1.begin(), cpy1.end());
std::sort(cpy2.begin(), cpy2.end());
return cpy1.compare(cpy2) == 0;
}
O(n) algorithm. Instead of sorting (which is O(n lg n)), count up the character occurrences in s1 and compare it to the character occurrences in s2.
#include <string>
#include <iostream>
#include <limits>
bool IsAnagram(const std::string& s1, const std::string& s2)
{
if (s1.size() != s2.size()) {
return false;
}
int count[std::numeric_limits<char>::max() + (std::size_t)1] = {};
for (auto c : s1) {
count[c]++;
}
for (auto c : s2) {
if (!count[c]) {
return false;
}
count[c]--;
}
return true;
}
int main(int argc, char **argv)
{
std::cout << IsAnagram(argv[1], argv[2]) << std::endl;
return 0;
}
There is already standard algorithm std::is_permutation that allows to perform the task simply
#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
int main()
{
std::string s( "aab" );
std::string t( "aba" );
std::cout << std::boolalpha
<< ( s.size() == t.size() &&
std::is_permutation( s.begin(), s.end(), t.begin() ) )
<< std::endl;
return 0;
}
The output is
true
So all ypu need is to see how the algorithm is realized.:)
If you want a separate function then it will look like
bool IsAnagram( const std::string &s1, const std::string &s2 )
{
return s1.size() == s2.size() &&
std::is_permutation( s1.begin(), s1.end(), s2.begin() );
}
To use std::sort is not a good approach because original strings will be changed or you have to pass them to the function by value.

Bit Operation For Finding String Difference

The following string of mine tried to find difference between two strings.
But it's horribly slow as it iterate the length of string:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int hd(string s1, string s2) {
// hd stands for "Hamming Distance"
int dif = 0;
for (unsigned i = 0; i < s1.size(); i++ ) {
string b1 = s1.substr(i,1);
string b2 = s2.substr(i,1);
if (b1 != b2) {
dif++;
}
}
return dif;
}
int main() {
string string1 = "AAAAA";
string string2 = "ATATT";
string string3 = "AAAAA";
int theHD12 = hd(string1,string2);
cout << theHD12 << endl;
int theHD13 = hd(string1,string3);
cout << theHD13 << endl;
}
Is there a fast alternative to do that?
In Perl we can have the following approach:
sub hd {
return ($_[0] ^ $_[1]) =~ tr/\001-\255//;
}
which is much2 faster than iterating the position.
I wonder what's the equivalent of it in C++?
Try to replace the for loop by:
for (unsigned i = 0; i < s1.size(); i++ ) {
if (b1[i] != b2[i]) {
dif++;
}
}
This should be a lot faster because no new strings are created.
Fun with the STL:
#include <numeric> //inner_product
#include <functional> //plus, equal_to, not2
#include <string>
#include <stdexcept>
unsigned int
hd(const std::string& s1, const std::string& s2)
{
// TODO: What should we do if s1.size() != s2.size()?
if (s1.size() != s2.size()){
throw std::invalid_argument(
"Strings passed to hd() must have the same lenght"
);
}
return std::inner_product(
s1.begin(), s1.end(), s2.begin(),
0, std::plus<unsigned int>(),
std::not2(std::equal_to<std::string::value_type>())
);
}
Use iterators:
int GetHammingDistance(const std::string &a, const std::string &b)
{
// Hamming distance is not defined for strings of different lengths.
ASSERT(a.length() == b.length());
std::string::const_iterator a_it = a.begin();
std::string::const_iterator b_it = b.begin();
std::string::const_iterator a_end = a.end();
std::string::const_iterator b_end = b.end();
int distance = 0;
while (a_it != a_end && b_it != b_end)
{
if (*a_it != *b_it) ++distance;
++a_it; ++b_it;
}
return distance;
}
Choice 1: Modify your original code to be as effecient as possable.
int hd(string const& s1, string const& s2)
{
// hd stands for "Hamming Distance"
int dif = 0;
for (std::string::size_type i = 0; i < s1.size(); i++ )
{
char b1 = s1[i];
char b2 = s2[i];
dif += (b1 != b2)?1:0;
}
return dif;
}
Second option use some of the STL algorithms to do the heavy lifting.
struct HammingFunc
{
inline int operator()(char s1,char s2)
{
return s1 == s2?0:1;
}
};
int hd(string const& s1, string const& s2)
{
int diff = std::inner_product(s1.begin(),s1.end(),
s2.begin(),
0,
std::plus<int>(),HammingFunc()
);
return diff;
}
Some obvious points that might make it faster:
Pass the strings as const references, not by value
Use the indexing operator [] to get characters, not a method call
Compile with optimization on
You use strings.
As explained here
The hunt for the fastest Hamming Distance C implementation
if you can use char* my experiements conclude that for Gcc 4.7.2 on an Intel Xeon X5650 the fastest general purpose hamming distance calculating function for small strings (char arrays) is:
// na = length of both strings
unsigned int HammingDistance(const char* a, unsigned int na, const char* b) {
unsigned int num_mismatches = 0;
while (na) {
if (*a != *b)
++num_mismatches;
--na;
++a;
++b;
}
return num_mismatches;
}
If your problem allows you to set an upper distance limit, so that you don't care for greater distances and this limit is always less than the strings' length, the above example can be furhterly optimized to:
// na = length of both strings, dist must always be < na
unsigned int HammingDistance(const char* const a, const unsigned int na, const char* const b, const unsigned int dist) {
unsigned int i = 0, num_mismatches = 0;
while(i <= dist)
{
if (a[i] != b[i])
++num_mismatches;
++i;
}
while(num_mismatches <= dist && i < na)
{
if (a[i] != b[i])
++num_mismatches;
++i;
}
return num_mismatches;
}
I am not sure if const does anything regarding speed, but i use it anyways...