public static final long stringToFlong(String s)
			throws FixedPointLongException {
		try {
			boolean negative = false;
			final int maxAfterPointLen = ("" + (1L << (OFFSET))).length();
			/*
			 * ("" + (1L << (LENGTH - 4))).length();
			 */
			if (s == null || s.equals(""))
				return 0;

			// split into integer and fractional parts
			int pointIndex = s.indexOf('.');
			int eIndex = s.indexOf('e');
			if (eIndex == -1)
				eIndex = s.indexOf('E');
			if (eIndex > 0 && pointIndex > 0 && eIndex <= pointIndex) {
				throw new FixedPointLongException(
						"stringToFlong: incorrect number format: \"" + s + "\"");
			}
			String beforePoint, afterPoint, eString;
			if (pointIndex < 0) {
				afterPoint = "0";
				if (eIndex < 0) {
					beforePoint = s;
					eString = "0";
				} else {
					beforePoint = s.substring(0, eIndex);
					eString = s.substring(eIndex + 1, s.length());
				}
			} else {
				beforePoint = s.substring(0, pointIndex);
				if (eIndex < 0) {
					afterPoint = s.substring(pointIndex + 1, s.length());
					eString = "0";
				} else {
					afterPoint = s.substring(pointIndex + 1, eIndex);
					eString = s.substring(eIndex + 1, s.length());
				}
			}

			// parse and check integer part
			if (beforePoint.charAt(0) == '-')
				negative = true;
			long intpart;
			try {
				intpart = Long.parseLong(beforePoint);
			} catch (NumberFormatException nfe) {
				throw new FixedPointLongException(
						"stringToFlong: cannot parse intpart of \"" + s + "\"");
			}
			if (negative)
				intpart = -intpart; // make positive for now
			if (bitsUsed(intpart) > LENGTH - OFFSET)
				throw new FixedPointLongException(
						"stringToFlong: number too large: \"" + s
								+ "\" : bitsUsed " + bitsUsed(intpart));

			// parse and check fractional part
			if (afterPoint.charAt(0) == '-')
				throw new FixedPointLongException(
						"stringToFlong: bad number format: \"" + s + "\"");
			if (afterPoint.length() > maxAfterPointLen) {

				/* commented out to remove warning */
				// String ap = afterPoint;
				afterPoint = afterPoint.substring(0, maxAfterPointLen);
			}
			long fracpart;
			try {
				fracpart = Long.parseLong(afterPoint);
			} catch (NumberFormatException nfe) {
				throw new FixedPointLongException(
						"stringToFlong: cannot parse fracpart of \"" + s
								+ "\": " + nfe);
			}
			if (fracpart != 0) {
				int oldbitsused = bitsUsed(fracpart);
				fracpart = fracpart << LENGTH - oldbitsused;
				for (int i = 0; i < afterPoint.length() - 1; i++) {
					fracpart /= 10;
				}
				fracpart = fracpart / 10 + (fracpart % 10 >= 5 ? 1 : 0);
				int shiftback = LENGTH - OFFSET - oldbitsused;
				if (shiftback > 0) {
					fracpart = fracpart >> shiftback - 1;
					fracpart = (fracpart + (fracpart & 1)) >> 1; // rounding
				} else {
					fracpart = fracpart << -shiftback;
				}
				if (bitsUsed(fracpart) > OFFSET + 1)
					throw new FixedPointLongException(
							"stringToFlong: error parsing " + s + " bitsused "
									+ bitsUsed(fracpart));
			}
			// output
			long result = ((intpart << OFFSET) + fracpart);

			// now do offset
			int shift;
			try {
				shift = Integer.parseInt(eString);
			} catch (NumberFormatException nfe) {
				throw new FixedPointLongException(
						"stringToFlong: cannot parse epart of \"" + s + "\"");
			}
			while (shift > 0) {
				long oldresult = result;
				result = result * 10;
				if (result / 10 != oldresult)
					throw new FixedPointLongException(
							"stringToFlong: overflow applying E shift when parsing \""
									+ s + "\"");
				shift--;
			}
			while (shift < 0) {
				result = result / 10;
				shift++;
			}

			result = negative ? -result : result;
			// System.out.println("Flong representation of " + s + " is " +
			// result + ", intpart " + intValue(result) + ", flongToString " +
			// flongToString(result));
			return result;
		} catch (Throwable t) {
			throw new FixedPointLongException(
					"FixedPointLong.stringToFlong: err "
							+ t.getClass().getName() + ":" + t.getMessage());
		}
	}