From ec172e1745c640f01c42d1e81b14f4c2ea69acd4 Mon Sep 17 00:00:00 2001 From: David Byers <david.byers@liu.se> Date: Tue, 21 Jul 2020 21:17:23 +0200 Subject: [PATCH] Rewrote olc-decode to use integer math. --- CHANGELOG | 3 +++ olc.el | 35 ++++++++++++++++++++++------------- test/olctest.el | 7 ++++--- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index deef8f4..9caef53 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ 2020-07-21 David Byers <david.byers@liu.se> + More integer math: + (olc-decode): Converted to use integer math. + Wrote texinfo documentation: * olc.el (olc-parse-length): Removed. Updated documentation comment. diff --git a/olc.el b/olc.el index 64715dc..1b7273b 100644 --- a/olc.el +++ b/olc.el @@ -264,10 +264,13 @@ coordinates, an empty code, and so forth). Since this function uses floating point calculations, the results are not identical to e.g. the C++ reference implementation. The differences, however, are extremely small." - (let ((parse (olc-parse-code code)) - (lat -90.0) - (lon -180.0) - (size 20.0)) + (let* ((parse (olc-parse-code code)) + (latscale (* (expt 20 4) (expt 5 5))) + (lonscale (* (expt 20 4) (expt 4 5))) + (lat (* latscale -90)) + (lon (* lonscale -180)) + (latsize (* latscale 20)) + (lonsize (* lonscale 20))) ;; We only deal with long codes (when (olc-parse-short parse) @@ -275,22 +278,28 @@ differences, however, are extremely small." ;; Process the pairs (mapc (lambda (pair) - (setq lat (+ lat (* size (olc-digit-value (car pair)))) - lon (+ lon (* size (olc-digit-value (cdr pair)))) - width size - height size - size (/ size 20.0))) + (setq lat (+ lat (* latsize (olc-digit-value (car pair)))) + lon (+ lon (* lonsize (olc-digit-value (cdr pair)))) + latsize (/ latsize 20) + lonsize (/ lonsize 20))) (olc-parse-pairs parse)) + ;; I'm too tired to figure out why + (setq latsize (* latsize 20) lonsize (* lonsize 20)) + ;; Process the grid (when (olc-parse-grid parse) (mapc (lambda (refine) - (setq width (/ width 4.0) height (/ height 5.0)) + (setq latsize (/ latsize 5) lonsize (/ lonsize 4)) (let ((coord (olc-digit-value refine))) - (setq lat (+ lat (* height (/ coord 4))) - lon (+ lon (* width (% coord 4)))))) + (setq lat (+ lat (* latsize (/ coord 4))) + lon (+ lon (* lonsize (% coord 4)))))) (olc-parse-grid parse))) - (olc-area-create :latlo lat :lonlo lon :lathi (+ lat height) :lonhi (+ lon width)))) + + (olc-area-create :latlo (/ lat (float latscale)) + :lonlo (/ lon (float lonscale)) + :lathi (/ (+ lat latsize) (float latscale)) + :lonhi (/ (+ lon lonsize) (float lonscale))))) (defun olc-encode (lat lon len) diff --git a/test/olctest.el b/test/olctest.el index bf2af42..e042345 100644 --- a/test/olctest.el +++ b/test/olctest.el @@ -18,8 +18,9 @@ (require 'cl-lib) -;; Decode still uses float arithmetic, so results can be slightly off -;; from the test cases. This is deemed acceptable. +;; Due to rounding and floating point representation we can't seem +;; to get closer than 1e-10 to the reference test cases, but sinze +;; it only affects decoding, that is an insignificant error level. (defvar olctest-decode-tolerance 0.0000000001) @@ -196,7 +197,7 @@ (defun olctest-run-all () "Run all tests." - (and (olctest-decode) + (and (olctest-decode)q (olctest-encode) (olctest-shortcodes) (olctest-validity) -- GitLab