#include <cstdio>
#include <algorithm>

using namespace std;
const int MOD(1000000000 + 7);
const int Max_NM(100050);
typedef long long int LL;

constexpr int Mult(int a, int b)
{
	return (a * 1LL) * b % MOD;
}

constexpr int Add(int a, int b)
{
	return a + b >= MOD ? a + b - MOD : a + b;
}

constexpr int Sub(int a, int b)
{
	return a - b < 0 ? a - b + MOD : a - b;
}

namespace io
{
	const int SIZE = (1 << 21) + 1;
	char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
	#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
	inline void flush (){fwrite (obuf, 1, oS - obuf, stdout);oS = obuf;}
	inline void putc (char x){*oS ++ = x;if (oS == oT) flush ();}
	template <class I>
	inline void gi (I &x) {for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
		for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;}
	template <class I>
	inline void print (I x){
		if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;while(x) qu[++ qr] = x % 10 + '0',  x /= 10;while (qr) putc (qu[qr--]);}
	struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io::gi;
using io::putc;
using io::print;

struct point
{
	int x, y;
	void give(const int &_x, const int &_y)
	{
		x = _x, y = _y;
	}
	inline bool operator<(const point &b) const
	{
		return x == b.x ? y > b.y : x < b.x;
	}
	inline bool operator==(const point &b) const
	{
		return x == b.x && y == b.y;
	}
};
int N, M, Tot, X[Max_NM], Y[Max_NM], L[Max_NM], R[Max_NM];
point V[Max_NM];

#define SUM (segt[cur].Sum)
#define LCH (segt[cur].lch)
#define RCH (segt[cur].rch)

struct node
{
	int Sum, lch, rch;
};
int tot, root;
node segt[Max_NM * 30];

void insert(int &cur, const int &pos, const int &v, const int &LEFT = 0, const int &RIGHT = 1000000000)
{
	if (!cur)
		segt[++tot] = segt[cur], cur = tot;
	SUM = Add(SUM, v);
	if (LEFT == RIGHT)
		return;
	int MID = LEFT + ((RIGHT - LEFT) >> 1);
	if (pos <= MID)
		insert(LCH, pos, v, LEFT, MID);
	else
		insert(RCH, pos, v, MID + 1, RIGHT);
}

int query(const int &cur, const int &l, const int &r, const int &LEFT = 0, const int &RIGHT = 1000000000)
{
	if (!cur)
		return 0;
	if (LEFT == l && RIGHT == r)
		return SUM;
	int MID = LEFT + ((RIGHT - LEFT) >> 1);
	if (r <= MID)
		return query(LCH, l, r, LEFT, MID);
	else
		if (l > MID)
			return query(RCH, l, r, MID + 1, RIGHT);
		else
			return Add(query(LCH, l, MID, LEFT, MID), query(RCH, MID + 1, r, MID + 1, RIGHT));
}

int main()
{
	gi(N), gi(M);
	for (int i = 1;i <= N;++i)
		gi(X[i]);
	for (int i = 1;i <= M;++i)
		gi(Y[i]);
	for (int i = 1, j = 0;i <= N;++i)
	{
		while (j + 1 <= M && Y[j + 1] <= X[i])
			++j;
		L[i] = j;
	}
	for (int i = N, j = M + 1;i >= 1;--i)
	{
		while (j - 1 >= 1 && Y[j - 1] >= X[i])
			--j;
		R[i] = j;
	}
	for (int i = 1;i <= N;++i)
		if (L[i] >= 1 && R[i] <= M && L[i] != R[i])
			V[++Tot].give(X[i] - Y[L[i]], Y[R[i]] - X[i]);
	sort(V + 1, V + 1 + Tot);
	Tot = unique(V + 1, V + 1 + Tot) - (V + 1);
	insert(root, 0, 1);
	for (int i = 1;i <= Tot;++i)
		insert(root, V[i].y, query(root, 0, V[i].y - 1));
	printf("%d", segt[root].Sum);
	return 0;
}
/*
考虑找到每个点左边的第一个点和右边的第一个点，设两个距离分别为l和r，那么这个点的信息可以用一个二元组(l, r)来表示
只考虑那些0 < l < INF和0 < r < INF的点，剩下的点最终到达的点是唯一确定的
假设一个点(l, r)最终到达了其左边的一个点，那么等价于有一个限制：整体移动到左边距离为l的点在整体移动到右边距离为r的点之前
那么如果有一个点(a, b)最终到达了其右边的一个点，等价于有一个限制：整体移动到右边距离为a的点在整体移动到左边距离为b的点之前
那么如果b >= r且a <= l，显然这两个限制是矛盾的。可以发现，只要不存在两个矛盾的限制，一定是一个合法的解
直接dp即可，而这个dp是可以用线段树优化的
*/

Measured memory_bytes: 22784