Play with http://connettiva.eu/newton/

How to compute the distance between us and a planet?

astronomical-almanac

https://packages.debian.org/source/sid/astronomical-almanac
C program written between 1987 and 2011

From http://www.moshier.net/
C program computes ephemerides of Sun, Moon, planets, comets, and stars using rigorous reduction methods from the _Astronomical Almanac_ and related sources. Includes PLAN404 series (see below) for positions of the planets, and a long-term extension of modern Lunar theory for the Moon's position. Reads ASCII file catalogues of stars and orbital elements. Displays all adjustments as it finds local azimuth and elevation, rise and set times, etc. Windows or MSDOS (Microsoft and Borland), Unix, VAX make files. Archive includes MSDOS executable program.

Quite complex. Better not to rewrite it.

Try it yourself

  • Debian and derivatives

 

 

  • Windows: download the zip, extract the .exe and run it from cmd

 

  • OS X: in a Debian VM.
sudo apt-get install aa

Run it inside a browser!

Poll a server?

No thanks!

We convert the C program to JavaScript using emscripten (emcc)

Normal compilation flow

gcc

assembler

machine code

linker

exe

clang

LLVM bytecode

machine code

linker

exe

Emscripten

emcc

LLVM bytecode

linker

asm.js

emcc source files

$ emcc -h

ERROR    root: no input files
note that input files without a known suffix are
ignored, make sure your input files end with one of:
('.c', '.C', '.i', '.cpp', '.cxx', '.cc', '.c++',
'.CPP', '.CXX', '.CC', '.C++', '.ii', '.m', '.mi',
'.mm', '.mii', '.bc', '.o', '.obj', '.dylib', '.so',
'.a', '.ll', '.h', '.hxx', '.hpp', '.hh', '.H',
'.HXX', '.HPP', '.HH')

Porting to asm.js

Basically I extracted the distance calculation algorithm

and made a standalone program of it.

It uses most of the .c files in the program.

 

Entry point: main in planet.c

planet.c

This is the function to call from the browser

#include <stdio.h>
#include "consts.h"

int main(int argc, char* argv[]) {
  double distance;
  double julian_day;
  int planet;
  sscanf(argv[1], "%lf", &julian_day);
  sscanf(argv[2], "%d", &planet);
  distance = km_to_planet(julian_day, planet);
  printf("%f\n", distance);
}

makefile

CC= emcc

NODE_CFLAGS=  -O2 --closure 1 --emit-symbol-map

BROWSER_CFLAGS = -O2 --closure 1 --emit-symbol-map -s MODULARIZE=1 \
   -s EXPORTED_FUNCTIONS="['_km_to_planet']"
...
PLANET_OBJS = planet.o planet_distance.o distance.o consts.o \
...
INCS = kep.h plantbl.h

all: aa conjunct moonrise planet
...

planet: $(PLANET_OBJS) $(INCS)
        $(CC) $(NODE_CFLAGS) -o planet-node.js $(PLANET_OBJS) -lm
        $(CC) $(BROWSER_CFLAGS) -o planet.js $(PLANET_OBJS) -lm

%.o: %c
        $(CC) $(INCS) $<

Compiling

The files are big but they contain all the libc functions needed by the algorithm, rewritten in asm.js

 

--closure 1 removed all the unused C functions

 

$ make -j

$ ll *js
-rw-rw-r-- 1 montra montra 234494 Jul  3 22:13 aa.js
-rw-rw-r-- 1 montra montra 210749 Jul  3 22:13 conjunct.js
-rw-rw-r-- 1 montra montra    811 Jun 24 16:41 julian_day.js
-rw-rw-r-- 1 montra montra 208694 Jul  3 22:13 moonrise.js
-rw-rw-r-- 1 montra montra 129124 Jul  3 22:13 planet.js
-rw-rw-r-- 1 montra montra 187395 Jul  3 22:13 planet-node.js

Node.js & the browser

Command line. Inputs: julian date and the number of the planet 

Browser module with Module declaration because of -s MODULARIZE=1

$ node planet-node.js $(node julian_day.js) 4 # Mars
386760399.250331
$ less planet-node.js  # minified because of -O2
var f;f||(f=eval("(function() { try { return Module ||
 {} } catch(e) { return {} } })()"));var ...
$ less planet.js
var Module = function(Module) {
  Module = Module || {};

var e;e||(e=eval("(function() { try { return Module || {} } ...

Symbols

Lists of the functions used by the modules

$ ll *symbols
-rw-rw-r-- 1 montra montra 2855 Jul  3 22:13 aa.js.symbols
-rw-rw-r-- 1 montra montra 2602 Jul  3 22:13 conjunct.js.symbols
-rw-rw-r-- 1 montra montra 2470 Jul  3 22:13 moonrise.js.symbols
-rw-rw-r-- 1 montra montra 1694 Jul  3 22:13 planet.js.symbols
-rw-rw-r-- 1 montra montra 2266 Jul  3 22:13 planet-node.js.symbols

$ less planet.js.symbols
da:_fabs
Db:_strlen
fa:_exp
ib:_g2plan
hb:_g3plan
...

Heap

The heap of the modules. It's either an array in the .js file or the .mem binary file. Tradeoffs:

  • .mem: faster script startup but a separate HTTP call.
  • .js: slower startup, same HTTP call.

 

Generated with -O2 and ontrolled by --memory-init-file

$ ll *mem
-rw-rw-r-- 1 montra montra 167792 Jul  3 22:13 aa.js.mem
-rw-rw-r-- 1 montra montra  50576 Jul  3 22:13 conjunct.js.mem
-rw-rw-r-- 1 montra montra  51088 Jul  3 22:13 moonrise.js.mem
-rw-rw-r-- 1 montra montra 152776 Jul  3 22:13 planet.js.mem
-rw-rw-r-- 1 montra montra 153344 Jul  3 22:13 planet-node.js.mem

Copy to the web app

$ cp planet.js planet.js.mem planet.js.symbols ../newton
$ cd !$
$ less index.html
...
<script src="planet.js"></script>
<script src="newton-client.bundle.js"></script>
...
$ less newton-client.js
// this makes the asm.js module available to JavaScript
var kmToPlanet = Module().cwrap("km_to_planet", "number", 
                                ["number", "number"]);
...
// computes the Julian date, with decimals
var now = new Date().getTime() / 86400000 + 2440587.5;

var distanceKm = Big(kmToPlanet(now, selectedPlanet.id));
// Big: https://github.com/MikeMcl/big.js
// arbitrary-precision decimal arithmetic

Finally...

Repositories

web app https://github.com/pmontrasio/newton-says

asm.js module https://github.com/pmontrasio/astronomical-almanac-js


PS: If you like to know more about the planets of the
Solar System you'll love
https://bubbl.in/book/the-solar-system-by-marvin-danig

$ beefy newton-client.js:newton-client.bundle.js \
     --url http://192.168.1.131:9966

Newton and asm.js

By Paolo Montrasio

Newton and asm.js

How to power a JavaScript front end application with an old C program compiled to asm.js. Walkthrough and links to the source repositories.

  • 798
Loading comments...