HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Gravity problem solver in Factor

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
problemgravitysolverfactor

Problem

After answering a question about Factor, I decided that it looked interesting. To get the hang of the syntax and such, I decided to write some basic physics code to "solve" the three-body problem. Then, I realized that math is harder than I thought it would be, so instead I just made a vocabulary to solve some basic problems about classical gravitational attraction.

I'm looking for advice on:

  • Idiomatic-ness: The functions feel pretty long for Factor, but they seem about as short as they'll get.



  • Naming: Some of my function names are subpar, but I can't find better names for them.



  • Separation: I feel like the vector arithmetic should be in its own vocabulary, but I'm not sure. Also, I have no idea how to do that.



  • Removing rounding errors: The program is fairly accurate, but some rounding error leads to ever-so-slightly wrong numbers (i.e. \$49.99999999999999\$ instead of \$50\$)



```
USING: locals math.functions math.vectors math.trig math.constants ;
IN: q.physics.gravitational-attraction

TUPLE: body
{ mass initial: 0 }
{ position initial: { 0 0 } }
{ velocity initial: { 0 0 } }
;
:: array>body ( array -- obj )
body new
array first >>mass
array second 2 head >>position
array third 2 head >>velocity
;
: >body ( mass position velocity -- obj )
3array array>body
;

! Constants
SYMBOLS: G ;
! Throws an error if it's 6.674e−11 so let's use 1
1 G set

:: vector-between ( from to -- v )
to first from first -
to second from second -
2array
;

:: dot ( u v -- rad )
u first v first u second v second +
u first sq u second sq + sqrt v first sq v second sq + sqrt *
/
;
: angle-between ( u v -- rad ) dot ;

:: v+ ( u v -- sum )
u first v first +
u second v second +
2array
;

:: s*v ( k v -- scaled )
v first k *
v second k *
2array
;

:: -1*v ( v -- neg )
v first -1 *
v second -1 *
2array
;

:: magnitude ( v -- num )
v first sq v second sq + sqrt
;

:: unit ( v -- unit )
v magnitude :> len

Solution

I'm not quite skilled enough at Factor yet to review your code in full, but I would just like to note as a response to


I don't know the math well enough to test the edge cases, but I did check with this code

Factor has really slick builtin unit-testing. Here are the docs; I'll pull an example from my factor/work directory:

USING: tools.test mk-initialism ;
IN: mk-initialism.tests

{ "LASER" } [ "Light Ablah by S of Ed Radiof" >initialism ] unit-test
{ "USA"   } [ "United S OF Americaof" >initialism ]         unit-test
{ "USA"   } [ "united states and america" >initialism ]     unit-test
{ "JTW"   } [ "Jordan Of the World" >initialism ]           unit-test


To create the test file, open the listener and do:

USE: tools.scaffold
"q.physics.gravitational-attraction" scaffold-tests


To run the tests, just run "q.physics.gravitational-attraction" test.

Code Snippets

USING: tools.test mk-initialism ;
IN: mk-initialism.tests

{ "LASER" } [ "Light Ablah by S of Ed Radiof" >initialism ] unit-test
{ "USA"   } [ "United S OF Americaof" >initialism ]         unit-test
{ "USA"   } [ "united states and america" >initialism ]     unit-test
{ "JTW"   } [ "Jordan Of the World" >initialism ]           unit-test
USE: tools.scaffold
"q.physics.gravitational-attraction" scaffold-tests

Context

StackExchange Code Review Q#95403, answer score: 2

Revisions (0)

No revisions yet.