#include<bits/stdc++.h>
using namespace std;

namespace HABIT{
    #define f(a,b,c,d) for(register int a=b,c=d;a<=c;a++)
    #define g(a,b,c,d) for(register int a=b,c=d;a>=c;a--)
    #define LOCAL
    typedef int i32;
    typedef unsigned int u32;
    typedef long long int i64;
    typedef unsigned long long int u64;
    typedef pair<i64,i64> pii;
    const i32 MAXN=2e5+10;
    typedef i32 ar[MAXN];
    
    template<typename T> inline T Max(T a) { return a; }
    template<typename T,typename... Args> inline T Max(T a,Args... args){
        T b=Max(args...);
        return (a>b)?a:b;
    }
    template<typename T> inline T Min(T a) { return a; }
    template<typename T,typename... Args> inline T Min(T a,Args... args){
        T b=Min(args...);
        return (a<b)?a:b;
    }

    #ifdef LOCAL
        inline char gc() { return getchar(); }
    #else
        inline char gc() {
            static char s[1<<20|1]={0},*p1=s,*p2=s;
            return (p1==p2)&&(p2=(p1=s)+fread(s,1,1<<20,stdin),p1==p2)?EOF:*(p1++);
        }
    #endif
    inline i64 read(){
        register i64 ans=0;register char c=gc();register bool neg=0;
        while(c<48||c>57) neg^=!(c^'-'),c=gc();
        while(c>=48&&c<=57) ans=(ans<<3)+(ans<<1)+(c^48),c=gc();
        return neg?-ans:ans;
    }

    char Output_Ans[1<<20|1],*Output_Cur=Output_Ans;
    inline void output() { Output_Cur-=fwrite(Output_Ans,1,Output_Cur-Output_Ans,stdout); }
    inline void print(char c){
        if(Output_Cur-Output_Ans+1>>20) output();
        *(Output_Cur++)=c;
    }
    inline void print(char *s) { while(*s) print( *(s++) ); }
    inline void print(u64 x){
        if(!x) { print('0'); return ; }
        char buf[30]={0},*p=buf+28;
        while(x) *(p--)=x%10+48,x/=10;
        print(p+1);
    }
    inline void print(u32 x) { print( (u64)x ); }
    inline void print(i64 x){
        if(x<0) print('-'),x=-x;
        print( (u64)x );
    }
    inline void print(i32 x){
        if(x<0) print('-'),x=-x;
        print( (u64)x );
    }
}
using namespace HABIT;

map<pii,i32> M;
i32 N,CntZero;
pii Vec[MAXN],VVec[MAXN];
const i64 MOD=1000000007;

inline i32 findit(const pii &v){
    if( M.find(v)!=M.end() )
        return M[v];
    return -1;
}

inline pii baseVec(const pii &v){
    pii u=v;
    i64 g=__gcd(abs(u.first),abs(u.second));
    u.first/=g;
    u.second/=g;
    if(u.first>0) return u;
    if(u.first==0){
        u.second=abs(u.second);
        return u;
    }
    u.first=-u.first;
    u.second=-u.second;
    return u;
}

inline void pre(){
    N=read();
    f(i,1,I,N){
        i64 X=read(),Y=read();
        if(X==0&&Y==0){
            CntZero++;
            Vec[i].first=Vec[i].second=0;
            continue;
        }
        Vec[i]=baseVec( pii(X,Y) );
        VVec[i]=baseVec( pii(Y,-X) );
        if( M.find( Vec[i] )==M.end() ) M[ Vec[i] ]=0;
        if( M.find( VVec[i] )==M.end() ) M[ VVec[i] ]=0;
        M[ Vec[i] ]++;
    }
}

inline i64 fpow(i64 a,i64 x){
    i64 ans=1;
    for(;x;x>>=1,a=a*a%MOD) if(x&1) ans=ans*a%MOD;
    return ans;
}

int main(){
    pre();
    i64 Ans=1;
    f(i,1,I,N){
        i32 N1=M[ Vec[i] ],N2=M[ VVec[i] ];
        M[ Vec[i] ]=M[ VVec[i] ]=0;
        Ans=(fpow(2,N1)+fpow(2,N2)-1)%MOD*Ans%MOD;
    }
    Ans=(Ans-1+CntZero)%MOD;
    print(Ans);
    output();
    return 0;
}