Skip to content

Commit

Permalink
Merge pull request #2925 from andrioni/hexliteral
Browse files Browse the repository at this point in the history
Add hexadecimal float literals (closes #2863)
  • Loading branch information
JeffBezanson committed Apr 26, 2013
2 parents 6f88b42 + dca8f0a commit c8b99d9
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 2 deletions.
14 changes: 14 additions & 0 deletions doc/manual/integers-and-floating-point-numbers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,20 @@ Values can be converted to ``Float32`` easily::
julia> typeof(ans)
Float32

Hexadecimal floating-point literals are also valid, but only as ``Float64`` values::

julia> 0x1p0
1.0

julia> 0x1.8p3
12.0

julia> 0x.4p-1
0.125

julia> typeof(ans)
Float64

Floating-point zero
~~~~~~~~~~~~~~~~~~~

Expand Down
16 changes: 16 additions & 0 deletions src/flisp/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ int isnumtok_base(char *tok, value_t *pval, int base)
return 1;
}
}
// hexadecimal float literals
else if (((tok[0]=='0' && tok[1]=='x') || (base == 16)) &&
strpbrk(tok, "pP")) {
d = strtod(tok, &end);
if (*end == '\0') {
if (pval) *pval = mk_double(d);
return 1;
}
// floats can end in f or f0
if (end > tok && end[0] == 'f' &&
(end[1] == '\0' ||
(end[1] == '0' && end[2] == '\0'))) {
if (pval) *pval = mk_float((float)d);
return 1;
}
}

if (tok[0] == '+') {
if (!strcmp(tok,"+NaN") || !strcasecmp(tok,"+nan.0")) {
Expand Down
8 changes: 8 additions & 0 deletions src/flisp/unittest.lsp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@
(assert (not (eqv? -0.0 0.0)))
(assert (= 0.0 -0.0))

; hexadecimal float literals
(assert (= 12.0 0x1.8p3))
(assert (= 0.1875 0x1.8p-3))
(assert (= 0.5 0x.8p0))
(assert (= 12.0 0x1.8p3f))
(assert (= 0.1875 0x1.8p-3f))
(assert (= 0.5 0x.8p0f))

; this crashed once
(for 1 10 (lambda (i) 0))

Expand Down
7 changes: 5 additions & 2 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
(let ((str (open-output-string))
(pred char-numeric?)
(is-float32-literal #f)
(is-hex-float-literal #f)
(leadingzero #f))
(define (allow ch)
(let ((c (peek-char port)))
Expand Down Expand Up @@ -250,12 +251,13 @@
(read-digs #f)
(disallow-dot)))))
(let ((c (peek-char port)))
(if (or (eqv? c #\e) (eqv? c #\E) (eqv? c #\f))
(if (or (eqv? c #\e) (eqv? c #\E) (eqv? c #\f) (eqv? c #\p) (eqv? c #\P))
(begin (read-char port)
(let ((d (peek-char port)))
(if (and (not (eof-object? d))
(or (char-numeric? d) (eqv? d #\+) (eqv? d #\-)))
(begin (set! is-float32-literal (eqv? c #\f))
(set! is-hex-float-literal (or (eqv? c #\p) (eqv? c #\P)))
(write-char c str)
(write-char (read-char port) str)
(read-digs #f)
Expand All @@ -274,7 +276,8 @@
(else 10)))
(n (string-to-number s r)))
(if n
(cond ((eq? pred char-hex?) (sized-uint-literal n s 4))
(cond (is-hex-float-literal (double n))
((eq? pred char-hex?) (sized-uint-literal n s 4))
((eq? pred char-oct?) (sized-uint-oct-literal n s))
((eq? pred char-bin?) (sized-uint-literal n s 1))
(is-float32-literal (float n))
Expand Down
58 changes: 58 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,64 @@ end
@test isa(1f1,Float32)
@test 1f1 == 10.

# hexadecimal float literals
@test 0x1p0 === 1.
@test 0x1p1 === 2.
@test 0x.1p0 === 0.0625
@test 0x.1p1 === 0.125
@test 0xfp0 === 15.
@test 0xfp1 === 30.
@test 0x.fp0 === 0.9375
@test 0x.fp1 === 1.875
@test 0x1.p0 === 1.
@test 0x1.p1 === 2.
@test 0xf.p0 === 15.
@test 0xf.p1 === 30.
@test 0x1.0p0 === 1.
@test 0x1.0p1 === 2.
@test 0x1.1p0 === 1.0625
@test 0x1.1p1 === 2.125
@test 0x1.fp0 === 1.9375
@test 0x1.fp1 === 3.875
@test 0xf.0p0 === 15.
@test 0xf.0p1 === 30.
@test 0xf.1p0 === 15.0625
@test 0xf.1p1 === 30.125
@test 0xf.fp0 === 15.9375
@test 0xf.fp1 === 31.875
@test 0x1P0 === 1.
@test 0x1P1 === 2.
@test 0x.1P0 === 0.0625
@test 0x.1P1 === 0.125
@test 0xfP0 === 15.
@test 0xfP1 === 30.
@test 0x.fP0 === 0.9375
@test 0x.fP1 === 1.875
@test 0x1.P0 === 1.
@test 0x1.P1 === 2.
@test 0xf.P0 === 15.
@test 0xf.P1 === 30.
@test 0x1.0P0 === 1.
@test 0x1.0P1 === 2.
@test 0x1.1P0 === 1.0625
@test 0x1.1P1 === 2.125
@test 0x1.fP0 === 1.9375
@test 0x1.fP1 === 3.875
@test 0xf.0P0 === 15.
@test 0xf.0P1 === 30.
@test 0xf.1P0 === 15.0625
@test 0xf.1P1 === 30.125
@test 0xf.fP0 === 15.9375
@test 0xf.fP1 === 31.875

# eps / realmin / realmax
@test 0x1p-52 == eps()
@test 0x1p-52 + 1 != 1
@test 0x1p-53 + 1 == 1
@test 0x1p-1022 == realmin()
@test 0x1.fffffffffffffp1023 == realmax()
@test isinf(nextfloat(0x1.fffffffffffffp1023))

# custom rounding and significant-digit ops
function approx_eq(a, b, tol)
abs(a - b) < tol
Expand Down

0 comments on commit c8b99d9

Please sign in to comment.