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

#define ll long long
const int N = 200005;

const int mod = 1e9 + 7;
inline int add(int x, int y){ x += y; if(x >= mod) x -= mod; return x;}
inline int sub(int x, int y){ x -= y; if(x < 0) x += mod; return x;}
inline int mul(int x, int y){ return (x * 1ll * y) % mod;}
inline int powr(int a, ll b){
	int x = 1 % mod;
	while(b){
		if(b & 1) x = mul(x, a);
		a = mul(a, a);
		b >>= 1;
	}
	return x;
}
inline int inv(int a){ return powr(a, mod - 2);}
const int inv2 = (mod + 1)/2;

int l[N], r[N], A[N];
int pref[N];
int prefmax[N], suffmax[N], perm[N];
bool cmp(int i, int j){ return A[i] > A[j];}
int sum(int i){
	return ((i * 1ll * (i + 1)) / 2) % mod;
}
set<int> added, st;
map<int, int> compress;
int ulta[N];

const int M = N * 80;
int lft[M], rgt[M], val[M];
int cnt;
struct persistent_segtree{
	int root[N];
	persistent_segtree(){root[0] = 0;}	
	void ADD(int v, int value, int rt, int newrt, int s = 0, int e = N){
		val[newrt] = add(val[rt], value);
		if(s == e){
			return;
		}
		int mid = (s + e) >> 1;
		if(v <= mid){
			// right remains same
			rgt[newrt] = rgt[rt];
			lft[newrt] = ++cnt;
			ADD(v, value, lft[rt], lft[newrt], s, mid);
		}
		else{
			// left remains same
			lft[newrt] = lft[rt];
			rgt[newrt] = ++cnt;
			ADD(v, value, rgt[rt], rgt[newrt], mid + 1, e);
		}
	}
	void ADD(int i, int v, int value){
		root[i] = ++cnt;
		ADD(v, value, root[i - 1], root[i]);
	}
	int GET(int l, int r, int rt, int s = 0, int e = N){
		if(!rt || l > e || s > r) return 0;
		if(s >= l && e <= r) return val[rt];
		int mid = (s + e) >> 1;
		return add(GET(l, r, lft[rt], s, mid), GET(l, r, rgt[rt], mid + 1, e));
	}
	int get(int l, int r, int x, int y){
		if(l > r) return 0;
		return sub(GET(x, y, root[r]), GET(x, y, root[l - 1]));
	}
	void trace(int rt, int s = 1, int e = N){
		if(!rt) return;
		int mid = (s + e) >> 1;
		trace(lft[rt], s, mid);
		trace(rgt[rt], mid + 1, e);
	}
} tree1, tree2, tree3, tree4;

int main(){
	int n, mx = 0;
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> A[i];
		mx = max(mx, A[i]);
		prefmax[i] = mx;
		perm[i] = i;
		st.insert(A[i]);
	}
	sort(perm + 1, perm + n + 1, cmp);
	added = {0, n + 1};
	for(int i = 1; i <= n; i++){
		int ind = perm[i];
		auto it = added.upper_bound(ind);
		auto it2 = it;
		it--;
		l[ind] = ind - (*it) - 1;
		r[ind] = (*it2) - ind - 1;
		added.insert(ind);
	}
	for(int i = n; i >= 1; i--) suffmax[n - i + 1] = max(suffmax[n - i], A[i]);
	int ans = 0;
	for(int i = 1; i <= n; i++){
		int x = add(1, mul(l[i] + r[i], inv2));
		int y = mul(x, l[i] + 1);
		int cnt = mul(y, r[i] + 1);
		ans = add(ans, mul(A[i], cnt));
	}
	for(int k = 1; k <= n; k++){
		if(k > 2)  ans = add(ans, mul(mx, mul(n - k + 1, pref[k - 2])));
		pref[k] = add(pref[k - 1], n - k + 1);
	}
	int CNT = 0;
	for(int x : st) compress[x] = ++CNT, ulta[CNT] = x;

	for(int l2 = 1; l2 <= n; l2++){
		tree1.ADD(l2, compress[prefmax[l2]], 1);
		tree2.ADD(l2, compress[prefmax[l2]], l2 - 1);
		tree3.ADD(l2, compress[prefmax[l2]], prefmax[l2]);
		tree4.ADD(l2, compress[prefmax[l2]], mul(l2 - 1, prefmax[l2]));
	}

	for(int l1 = 1; l1 <= n; l1++){
		int MX = suffmax[l1];
		if(l1 != n){
			ans = add(ans, mul(mul(MX, l1), tree1.get(l1 + 1, n, 1, compress[MX] - 1)));
			ans = add(ans, mul(l1, tree3.get(l1 + 1, n, compress[MX], N)));
		}
		ans = add(ans, mul(MX, tree2.get(1, l1, 1, compress[MX] - 1)));
		ans = add(ans, tree4.get(1, l1, compress[MX], N));
	}

	printf("%d\n", ans);
}