Line data Source code
1 : /*
2 : * Package : Cbor
3 : * Author : S. Hamblett <steve.hamblett@linux.com>
4 : * Date : 12/12/2016
5 : * Copyright : S.Hamblett
6 : */
7 :
8 : part of cbor;
9 :
10 : /// Numeric handling support functions.
11 :
12 : /// Float handling support functions.
13 :
14 : /// Gets a half precision float from its int
15 : /// value.
16 : double getHalfPrecisionDouble(int val) {
17 4 : int t1 = val & 0x7fff; // Non-sign bits
18 4 : int t2 = val & 0x8000; // Sign bit
19 4 : final int t3 = val & 0x7c00; // Exponent
20 4 : t1 <<= 13; // Align mantissa on MSB
21 4 : t2 <<= 16; // Shift sign bit into position
22 4 : t1 += 0x38000000; // Adjust bias
23 4 : t1 = (t3 == 0 ? 0 : t1); // Denormalise as zero
24 4 : t1 |= t2; // re-insert sign bit
25 4 : final List<int> tmp = new List<int>();
26 12 : tmp.add((t1 >> 24) & 0xff);
27 12 : tmp.add((t1 >> 16) & 0xff);
28 12 : tmp.add((t1 >> 8) & 0xff);
29 8 : tmp.add(t1 & 0xff);
30 4 : final typed.Uint8Buffer buff = new typed.Uint8Buffer();
31 4 : buff.addAll(tmp);
32 8 : final ByteData bdata = new ByteData.view(buff.buffer);
33 4 : final double ret = bdata.getFloat32(0);
34 : return ret;
35 : }
36 :
37 : /// Gets a half precision integer value from a
38 : /// float.
39 : int getHalfPrecisionInt(double val) {
40 3 : final typed.Float32Buffer fBuff = new typed.Float32Buffer(1);
41 3 : fBuff[0] = val;
42 3 : final ByteBuffer bBuff = fBuff.buffer;
43 3 : final Uint8List uList = bBuff.asUint8List();
44 30 : final int intVal = uList[0] | uList[1] << 8 | uList[2] << 16 | uList[3] << 24;
45 3 : final int index = intVal >> 23;
46 3 : final int masked = intVal & 0x7FFFFF;
47 18 : final int hBits = baseTable[index] + ((masked) >> shiftTable[index]);
48 : return hBits;
49 : }
50 :
51 : /// Check if a double can be represented as half precision.
52 : /// Returns true if it can be.
53 : bool canBeAHalf(double value) {
54 : // Convert to half and back again.
55 2 : final int half = getHalfPrecisionInt(value);
56 2 : final double result = getHalfPrecisionDouble(half);
57 : // If the value is the same it can be converted.
58 2 : return result == value ? true : false;
59 : }
60 :
61 : /// Check if a double can be represented as single precision.
62 : /// Returns true if it can.
63 : bool canBeASingle(double value) {
64 : /// Convert to single and back again.
65 2 : final typed.Float32Buffer fBuff = new typed.Float32Buffer(1);
66 2 : fBuff[0] = value;
67 : // If the value is the same it can be converted.
68 2 : final double result = fBuff[0];
69 2 : return value == result ? true : false;
70 : }
71 :
72 : /// Bignum functions
73 :
74 : /// Bignum byte buffer to int. Returns null
75 : /// if the conversion fails.
76 : int bignumToInt(typed.Uint8Buffer buff, String sign) {
77 : // Convert to a signed hex string.
78 1 : String res = sign + "0x";
79 2 : for (int i in buff) {
80 1 : String tmp = i.toRadixString(16);
81 2 : if (tmp.length == 1) {
82 1 : tmp = "0" + tmp;
83 : }
84 1 : res += tmp;
85 : }
86 :
87 : // Try a parse
88 1 : final int value = int.parse(res, onError: (source) => null);
89 : return value;
90 : }
|