#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
inline int read()
{
int cur=0;
char ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') cur=cur*10+ch-'0',ch=getchar();
return cur;
}
struct Tree
{
ll sum,sqr; //sum : 区间和 ; sqr : 区间平方和
};
const int N=1e6+10,Mod=1e9+7;
int n,cnt;
int a[N],b[N],lst[N];
map<int,int> mp;
ll lazy[N<<2];
Tree tree[N<<2];
inline void fun(int root,int l,int r,int v)
{
tree[root].sqr=(tree[root].sqr+tree[root].sum*2*v+(r-l+1)*v*v)%Mod;
tree[root].sum=(tree[root].sum+(r-l+1)*v)%Mod;
lazy[root]+=v;
}
inline void pushdown(int root,int l,int r)
{
int mid=(l+r)>>1;
int lson=(root<<1);
int rson=(root<<1)|1;
fun(lson,l,mid,lazy[root]);
fun(rson,mid+1,r,lazy[root]);
lazy[root]=0;
}
void update(int root,int l,int r,int sp,int ep,int v)
{
if(r<sp || l>ep) return;
if(l>=sp && r<=ep)
{
fun(root,l,r,v);
return;
}
pushdown(root,l,r);
int mid=(l+r)>>1;
int lson=(root<<1);
int rson=(root<<1)|1;
update(lson,l,mid,sp,ep,v);
update(rson,mid+1,r,sp,ep,v);
tree[root].sum=tree[lson].sum+tree[rson].sum;
tree[root].sqr=tree[lson].sqr+tree[rson].sqr;
}
ll query(int root,int l,int r,int sp,int ep)
{
if(r<sp || l>ep) return 0;
if(l>=sp && r<=ep) return tree[root].sqr;
pushdown(root,l,r);
int mid=(l+r)>>1;
int lson=(root<<1);
int rson=(root<<1)|1;
ll la=query(lson,l,mid,sp,ep);
ll ra=query(rson,mid+1,r,sp,ep);
return (la+ra)%Mod;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i]=b[i]=read();
lst[i]=n+1;
}
sort(b+1,b+n+1);
for(int i=1;i<=n;i++)
{
if(!mp[b[i]])
{
mp[b[i]]=++cnt;
}
}
for(int i=1;i<=n;i++) a[i]=mp[a[i]];
ll ans=0;
for(int i=n;i>=1;i--)
{
update(1,1,n,i,lst[i]-1,1);
ans+=query(1,1,n,i,n)%Mod;
ans%=Mod;
lst[a[i]]=i;
}
printf("%lld",ans);
return 0;
}