[Swift-commit] r7793 - in demo/xsede.2014.0425: . src src/c-ray

wilde at ci.uchicago.edu wilde at ci.uchicago.edu
Thu Apr 24 12:50:23 CDT 2014


Author: wilde
Date: 2014-04-24 12:50:23 -0500 (Thu, 24 Apr 2014)
New Revision: 7793

Added:
   demo/xsede.2014.0425/src/
   demo/xsede.2014.0425/src/c-ray/
   demo/xsede.2014.0425/src/c-ray/Makefile
   demo/xsede.2014.0425/src/c-ray/README
   demo/xsede.2014.0425/src/c-ray/RUN
   demo/xsede.2014.0425/src/c-ray/c-ray.c
   demo/xsede.2014.0425/src/c-ray/scene.cr
   demo/xsede.2014.0425/src/c-ray/sphfract.cr
Log:
Add stripped-down c-ray source dir.

Added: demo/xsede.2014.0425/src/c-ray/Makefile
===================================================================
--- demo/xsede.2014.0425/src/c-ray/Makefile	                        (rev 0)
+++ demo/xsede.2014.0425/src/c-ray/Makefile	2014-04-24 17:50:23 UTC (rev 7793)
@@ -0,0 +1,23 @@
+#obj = c-ray-mt.o
+bin = c-ray
+
+CC = gcc
+CFLAGS = -O3 -ffast-math
+
+$(bin): $(obj)
+	$(CC) -o $@ $(bin).c -lm -lpthread
+
+#$(bin): $(obj)
+#	$(CC) -o $@ $(obj) -lm -lpthread
+
+.PHONY: clean
+clean:
+	rm -f $(obj) $(bin)
+
+.PHONY: install
+install:
+	cp $(bin) /usr/local/bin/$(bin)
+
+.PHONY: uninstall
+uninstall:
+	rm -f /usr/local/bin/$(bin)

Added: demo/xsede.2014.0425/src/c-ray/README
===================================================================
--- demo/xsede.2014.0425/src/c-ray/README	                        (rev 0)
+++ demo/xsede.2014.0425/src/c-ray/README	2014-04-24 17:50:23 UTC (rev 7793)
@@ -0,0 +1,395 @@
+
+                     C-Ray Simple Raytracing Tests
+
+           http://www.futuretech.blinkenlights.nl/c-ray.html
+
+              By: John Tsiombikas <nuclear at siggraph.org>
+
+       Test suite compiled by: Ian Mapleson <mapesdhs at yahoo.com>
+
+                       Last Change: 10/Apr/2008
+
+
+1. Introduction
+2. The C-Ray Tests (how to compile)
+3. Running the Tests
+4. Submitting Results
+5. Background
+6. Appendix A: Invalid Tests
+
+**********************************************************************
+
+1. Introduction
+
+C-Ray is a simple raytracer written by John Tsiombikas; in his
+own words, it is:
+
+  "...an extremely small program I did one day to figure out how
+  would the simplest raytracer program look like in the least
+  ammount of code lines."
+
+The relevant discussion on Nekochan is at:
+
+  http://forums.nekochan.net/viewtopic.php?f=3&t=15719
+
+The default data set is very small, so C-ray really only tests the pure
+floating-point (fp) speed of a CPU core (or multiple CPUs/cores using the
+threaded version), ie. RAM speed is not a significant factor. John said:
+
+  This thing only measures 'floating point CPU performance' and
+  nothing more, and it's good that nothing else affects the results.
+  A real rendering program/scene would be still CPU-limited meaning
+  that by far the major part of the time spent would be CPU time in
+  the fpu, but it would have more overhead for disk I/O, shader
+  parsing, more strain for the memory bandwidth, and various other
+  things. So it's a good approximation being a renderer itself, but
+  it's definitely not representative."
+
+Nevertheless, the results are certainly interesting:
+
+  http://www.futuretech.blinkenlights.nl/c-ray.html
+
+If you wish to submit your own results, follow the instructions given
+below. Send the data to me, not to John, and I will add them to the
+relevant tables; please include all requested details.
+
+Comments and feedback welcome!
+
+Ian.
+
+mapesdhs at yahoo.com
+sgidepot at blueyonder.co.uk
+http://www.futuretech.blinkenlights.nl/sgidepot/
+
+**********************************************************************
+
+2. The C-Ray Tests
+
+Two programs are included in this archive for testing:
+
+c-ray-f:
+
+  This is for single-CPU systems, or for testing just a single core
+  of a multi-core CPU.
+
+c-ray-mt:
+
+  This is the multithreaded version for testing multi-CPU systems, and/or
+  systems with more than one CPU core. Note that on some systems c-ray-mt
+  with just one thread may be faster than c-ray-f. Use whichever version
+  gives you the best results in each case. Use the -t option to specify
+  the number of threads; without the -t option, only 1 thread is used.
+
+Compile the source files for your target platform with gcc or whatever
+compiler you have. Just enter 'make', though feel free to add any arch-
+specific optimizations for your compiler in CFLAGS first. By default,
+the Makefile is designed for use with GCC. If you are using an SGI and
+want to use MIPS Pro to compile the programs, then enter:
+
+  /bin/cp Makefile.mips Makefile
+
+and then enter 'make'.
+
+Note that the c-ray binaries as supplied were compiled for an SGI
+Octane2 R12K/R14 system (users of other SGI models should recompile
+if possible), while the example x86 binary in the x86 directory was
+compiled by John for a 3GHz P4.
+
+If you don't want to use make, then typical compile lines for each
+program on SGIs using MIPS Pro are as follows (in this case for an
+Octane system - use a different IP number for other SGI systems):
+
+  cc -O3 -mips4 -TARG:platform=ip30 -Ofast=ip30 c-ray-f.c -o c-ray-f -lm
+
+while for the threaded version the pthread library must be included:
+
+  cc -O3 -mips4 -TARG:platform=ip30 -Ofast=ip30 c-ray-mt.c -o c-ray-mt -lm -lpthread
+
+See the 'cc' man page for full details of available optimisation options.
+
+The file 'sgi.txt' has further example compile lines for SGI O2 and
+Octane machines, some with extra example optimisation options. Try
+them out, see which one works best on your system. Those using GCC
+should consult the gcc man page for full details of available options.
+
+NOTE: results for tests done with pre-run profiling/virtualisation
+compiler optimisations will NOT be accepted! (see Appendix A for details).
+
+Before running the tests, naturally you should shut down any other
+applications, processes, etc. which might interfere with the test.
+For example, on SGI systems, I shut down the mediad and sgi_apache
+daemons:
+
+  /etc/init.d/mediad stop
+  /etc/init.d/sgi_apache stop
+
+Better still, turn off timed, nsd, and rlogin remotely to run the tests.
+It should be possible to do the same thing on a Linux/BSD system.
+
+On a Windows machine, shut down all unnecessary processes, close any
+antivirus/firewall applications/processes, and it may be worthwhile
+forcing any pending idle tasks to complete before running the tests,
+ie. select Run from the Start menu and enter:
+
+  Rundll32.exe advapi32.dll,ProcessIdleTasks
+
+Assuming you are now ready to use the binary programs for the tests...
+
+**********************************************************************
+
+3. Running the Tests
+
+There are two data files used for the tests:
+
+'scene' is a simple environment, with just three reflective spheres.
+Examine scene.jpg to see the final image.
+
+'sphract' is a much more complex scenario, with dozens of spheres in
+a fractal pattern (see gen_fract.txt for details of how the scene
+description was created). Examine sphract.jpg to see the final image.
+
+There are four tests; the first is the shortest, the data from which
+are used for the main table on the results page. The tests are:
+
+
+  Test   Data File    Image Resolution     Oversampling
+
+   1.    scene        Default 800x600      NONE
+   2.    sphract      Default 800x600      NONE
+   3.    sphract      1024 x 768           8X
+   4.    scene        7500 x 3500          NONE
+
+If you are using a single-CPU system which only has one core, or wish
+to test just one CPU/core of a multi-CPU/core system, then run the
+tests with c-ray-f, or with c-ray-mt using just 1 thread. For systems
+with multiple CPUs/cores, please submit results for just a single
+CPU/core aswell as the fastest results for using all CPUs/cores (this
+allows one to see how well parallel systems scale).
+
+On UNIX systems, the programs receive the scene description data from
+the standard input and send the results (the image created) to the
+standard output. To run the first test on a UNIX system, enter:
+
+  cat scene | ./c-ray-f > foo.ppm
+
+On a Windows system, enter the following in a Command window:
+
+  c-ray-f -i scene -o foo.ppm
+
+The output will resemble the following (in this case run on a R14000
+550MHz SGI Octane2):
+
+  Rendering took: 1 seconds (1888 milliseconds)
+
+The result to submit is the number of milliseconds. Run each test
+several times if possible to observe a typical result. It's up to
+you whether you submit a typical result or the fastest overall result.
+
+If you have a multi-CPU/core system, now run the test multithreaded with
+c-ray-mt, using the -t option to specify the number of threads, eg.
+
+     UNIX:   cat scene | ./c-ray-mt -t 32 > foo.ppm
+  Windows:   c-ray-mt -t 32 -i scene -o foo.ppm
+
+For multi-CPU/core systems, the optimum number of threads varies
+greatly from one system to another, though a good estimate is 16
+times the number of cores. Try different numbers, eg. 32, 64, 128,
+or some inbetween number such as 40, 60, etc. But also try smaller
+number too, eg. just 8 threads for a quad-core system.
+
+The maximum number of threads c-ray-mt can use is the vertical
+resolution of the output image. As the number of threads increases,
+eventually the speedup obtained by the parallel processing will be
+outweighed by the overhead cost of managing the threads. Experiment
+to find what works best for each test.
+
+Thus, for the other tests, the commands to enter on a UNIX system
+would be as follows, using 32 threads just as an example here:
+
+  cat sphract | ./c-ray-f > foo.ppm
+  cat sphract | ./c-ray-mt -t 32 > foo.ppm
+  cat sphract | ./c-ray-f -s 1024x768 -r 8 > foo.ppm
+  cat sphract | ./c-ray-mt -t 32 -s 1024x768 -r 8 > foo.ppm
+  cat scene | ./c-ray-f -s 7500x3500 > foo.ppm
+  cat scene | ./c-ray-mt -t 32 -s 7500x3500 > foo.ppm
+
+while on a Windows system these would be:
+
+  c-ray-f -i sphract -o foo.ppm
+  c-ray-mt -t 32 -i sphract -o foo.ppm
+  c-ray-f -s 1024x768 -r 8 -i sphract -o foo.ppm
+  c-ray-mt -t 32 -s 1024x768 -r 8 -i sphract -o foo.ppm
+  c-ray-f -s 7500x3500 -i scene -o foo.ppm
+  c-ray-mt -t 32 -s 7500x3500 -i scene -o foo.ppm
+
+If you don't want to bother experimenting, then the script RUN.full
+will execute all the tests, with the c-ray-mt tests done using 32
+threads, but remember 32 threads might not be optimal for your system.
+
+**********************************************************************
+
+4. Submitting Results
+
+Do not send any results to John; instead, send all results to me at
+both of my email addresses (include "C-Ray" in the subject line):
+
+  mapesdhs at yahoo.com
+  sgidepot at blueyonder.co.uk
+
+Apart from the run-times reported by each test, please remember
+to state which tests are multithreaded and how many threads were
+used. Better still, just copy the on-screen text for each test.
+
+With respect to system information, state the type of system (name
+and/or model number), CPU details (name/model, type/speed/cache,
+no. of CPUs/cores), OS name/version (eg. for Linux, what name,
+kernel version/build), what compiler was used (name/version) and
+what extra options if any were employed. The online results page
+also shows the host name where available, but this is optional.
+
+Thus, for example, a system description might look like this:
+
+  SUN Fire X2100, Solaris 10, host name 'kobe'
+  Sun Studio 10 Compiler
+  AMD Opteron 175 2.2 GHz 1MB L2
+
+while for an SGI it might be:
+
+  SGI Octane2, IRIX 6.5.26m
+  MIPS Pro 7.4.3m (7.3 EOE)
+  Dual-R12000 400MHz (2MB L2)
+
+or a Windows system (in this case my own setup):
+
+  WinXP-32bit PC (SP2), Asrock AM2NF3 motherboard, 4GB DDR2/800 RAM
+  Athlon64 X2 6000+ 3.15GHz (overclocked)
+  Supplied x86 binary used (1 core only)
+
+You can also mention the system's RAM, disk, or anything else, but
+they're not essential.
+
+Note for SGI users: you can find out what eoe/dev compiler versions
+your system has installed by entering:
+
+  versions -b | grep compiler_
+
+eg. on my Octane2 this gives:
+
+  I  compiler_dev   05/14/2004  Base Compiler Development Environment, 7.3
+  I  compiler_eoe   07/13/2005  IRIX Standard Execution Environment (Base Compiler Headers and Libraries, 7.4.3m)
+
+**********************************************************************
+
+5. Background
+
+When I asked John about why he created C-Ray, he said:
+
+  This is just an extremely small program I did one day to figure
+  out how would the simplest raytracer program look like in the
+  least amount of code lines :)  It's not useful for anything apart
+  from benchmarking.
+
+  As part of my BSc dissertation project I did a really big and
+  feature-full ray tracer, which could be useful, supporting:
+  programmable shading, network rendering, monte carlo rendering
+  algorithms, etc. But it's big and buggy, slow, and incomplete
+  because I was rushing to finish it the last minute before the
+  deadline (as always) :)
+
+  So I scrapped the damn thing after that, and I'm starting from
+  scratch with a new design if I finish it and it proves to be
+  sucessful I'll let you know :)"
+
+
+I also asked John why the best c-ray-mt results seem to be obtained
+with a number of threads that is much larger than the number of
+CPUs/cores in a system, to which he replied:
+
+  Ian wrote:
+  > I also suspect more threads means the balanced load between
+  > the two CPUs is less affected by the possible differences in
+  > complexity between threads.
+
+  Bingo, each thread takes a bunch of scanlines, if the relative
+  complexity of the rendering calculations between the bunches(sic)
+  is not equal, then one thread may spend much more time calculating
+  than another thread. Of course that doesn't necessarily mean that
+  one "CPU" ends up calculating much more than the other since the
+  threads are not "bound" to any CPU, each CPU takes one of the
+  available ready-to-run threads each timeslice. Anyway having more
+  threads evens it out. I would guess about 4 times as many threads
+  as the CPUs [multiplied by the no. of cores per CPU] would be enough.
+
+
+I also asked John if there was any element of overhead processing
+to handle the results of the multiple threads. He said:
+
+  There's no such overhead. Each thread gets a pointer to the
+  appropriate location of the framebuffer, and stores every pixel
+  as it is calculated directly. Also any processing afterwards
+  (output of the PPM image) is done *after* timing stops.
+
+
+See the Nekochan thread for more discussion about C-Ray, including
+further comments by John.
+
+**********************************************************************
+
+6. Appendix A: Invalid Tests
+
+Results for tests done with pre-run profiling/virtualisation compiler
+optimisations will NOT be accepted! What does this mean? Read on...
+
+Someone emailed me to say they had been able to halve the test run
+times by using the following compilation/execution sequence:
+
+  XC="gcc -O3 -ffast-math -fomit-frame-pointer c-ray-f.c
+  -finline-limit=10000 -ftree-vectorize -fwhole-program
+  -fbranch-probabilities -ffunction-sections -o c-ray-f -lm" && $XC
+  -fprofile-generate && ./run > /dev/null 2>&1 && $XC -fprofile-use
+  && ./run && ./run && ./run && ./run
+
+with ./run containing:
+
+  #!/bin/sh
+  cat scene | ./c-ray-f > foo2.ppm
+
+The explanation was as follows:
+
+  What this does is to create an executable with profiling and
+  virtualization instructions, execute it in order to create "real life"
+  information and then recompile it using that information to better
+  optimize it without the need of "guessing" (which is what usually a
+  plain -O3 does). Doing this speeds up the execution a lot. Another
+  important thing was to increase the inline limit from 600 (or whatever
+  the default value is) to something big (like 10000) so more functions
+  will be inlined instead of called. The usage of "-fwhole-program" tells
+  to gcc that the .c file is the one and only source code file for the
+  program, so it will use all functions as static and will make all
+  "inline-able" functions, inline. This is another great speedup :-).
+
+My problem with this is that, by definition, the test has to be run
+multiple times in order to provide execution profiling data used to
+optimise the test for the final run. Thus, the real total run time spent
+to obtain the final result was not that much less or perhaps longer than
+just running the test a single time without this sort of execution
+profiling.
+
+I asked John about these optimisations; he said:
+
+  Hahaha :)
+  Yes I bet the biggest advantage was the profiling run and use of that
+  profiling information, and maybe also the whole program optimizations.
+  Both of which can't be done in real-life programs :)
+
+  The profiling information helps the compiler issue branch prediction
+  hints to the processor, and also do prefetches. The first one makes a
+  lot of difference in modern x86 CPUs with their huge execution
+  pipelines. If the branch prediction fails, you end up flushing the
+  pipeline and backtracking tens of instructions. Explicit prefetching,
+  would also make a big difference if the data set was bigger. I don't
+  think it helps here.
+
+This method of optimisation is certainly interesting, but I don't think
+it's appropriate for the C-Ray tests.
+

Added: demo/xsede.2014.0425/src/c-ray/RUN
===================================================================
--- demo/xsede.2014.0425/src/c-ray/RUN	                        (rev 0)
+++ demo/xsede.2014.0425/src/c-ray/RUN	2014-04-24 17:50:23 UTC (rev 7793)
@@ -0,0 +1,2 @@
+#!/bin/sh
+cat scene.cr | ./c-ray > scene.ppm


Property changes on: demo/xsede.2014.0425/src/c-ray/RUN
___________________________________________________________________
Added: svn:executable
   + *

Added: demo/xsede.2014.0425/src/c-ray/c-ray.c
===================================================================
--- demo/xsede.2014.0425/src/c-ray/c-ray.c	                        (rev 0)
+++ demo/xsede.2014.0425/src/c-ray/c-ray.c	2014-04-24 17:50:23 UTC (rev 7793)
@@ -0,0 +1,671 @@
+/* c-ray-mt - a simple multithreaded raytracing filter.
+ * Copyright (C) 2006 John Tsiombikas <nuclear at siggraph.org>
+ *
+ * You are free to use, modify and redistribute this program under the
+ * terms of the GNU General Public License v2 or (at your option) later.
+ * see "http://www.gnu.org/licenses/gpl.txt" for details.
+ * ---------------------------------------------------------------------
+ * Usage:
+ *   compile:  just type make
+ *              (add any arch-specific optimizations for your compiler in CFLAGS first)
+ *       run:  cat scene | ./c-ray-mt [-t num-threads] >foo.ppm
+ *              (on broken systems such as windows try: c-ray-mt -i scene -o foo.ppm)
+ *     enjoy:  display foo.ppm
+ *              (with imagemagick, or use your favorite image viewer)
+ * ---------------------------------------------------------------------
+ * Scene file format:
+ *   # sphere (many)
+ *   s  x y z  rad   r g b   shininess   reflectivity
+ *   # light (many)
+ *   l  x y z
+ *   # camera (one)
+ *   c  x y z  fov   tx ty tz
+ * ---------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <errno.h>
+#include <pthread.h>
+
+#define VER_MAJOR	1
+#define VER_MINOR	1
+#define VER_STR		"c-ray-mt v%d.%d\n"
+
+#if !defined(unix) && !defined(__unix__)
+#ifdef __MACH__
+#define unix		1
+#define __unix__	1
+#endif	/* __MACH__ */
+#endif	/* unix */
+
+/* find the appropriate way to define explicitly sized types */
+/* for C99 or GNU libc (also mach's libc) we can use stdint.h */
+#if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) || defined(__MACH__)
+#include <stdint.h>
+#elif defined(unix) || defined(__unix__)	/* some UNIX systems have them in sys/types.h */
+#include <sys/types.h>
+#elif defined(__WIN32__) || defined(WIN32)	/* the nameless one */
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int32 uint32_t;
+#endif	/* sized type detection */
+
+struct vec3 {
+	double x, y, z;
+};
+
+struct ray {
+	struct vec3 orig, dir;
+};
+
+struct material {
+	struct vec3 col;	/* color */
+	double spow;		/* specular power */
+	double refl;		/* reflection intensity */
+};
+
+struct sphere {
+	struct vec3 pos;
+	double rad;
+	struct material mat;
+	struct sphere *next;
+};
+
+struct spoint {
+	struct vec3 pos, normal, vref;	/* position, normal and view reflection */
+	double dist;		/* parametric distance of intersection along the ray */
+};
+
+struct camera {
+	struct vec3 pos, targ;
+	double fov;
+};
+
+struct thread_data {
+	pthread_t tid;
+	int sl_start, sl_count;
+
+	uint32_t *pixels;
+};
+
+void render_scanline(int xsz, int ysz, int sl, uint32_t *fb, int samples);
+struct vec3 trace(struct ray ray, int depth);
+struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth);
+struct vec3 reflect(struct vec3 v, struct vec3 n);
+struct vec3 cross_product(struct vec3 v1, struct vec3 v2);
+struct ray get_primary_ray(int x, int y, int sample);
+struct vec3 get_sample_pos(int x, int y, int sample);
+struct vec3 jitter(int x, int y, int s);
+int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp);
+void load_scene(FILE *fp);
+unsigned long get_msec(void);
+
+void *thread_func(void *tdata);
+
+#define MAX_LIGHTS		16				/* maximum number of lights */
+#define RAY_MAG			1000.0			/* trace rays of this magnitude */
+#define MAX_RAY_DEPTH	5				/* raytrace recursion limit */
+#define FOV				0.78539816		/* field of view in rads (pi/4) */
+#define HALF_FOV		(FOV * 0.5)
+#define ERR_MARGIN		1e-6			/* an arbitrary error margin to avoid surface acne */
+
+/* bit-shift ammount for packing each color into a 32bit uint */
+#ifdef LITTLE_ENDIAN
+#define RSHIFT	16
+#define BSHIFT	0
+#else	/* big endian */
+#define RSHIFT	0
+#define BSHIFT	16
+#endif	/* endianess */
+#define GSHIFT	8	/* this is the same in both byte orders */
+
+/* some helpful macros... */
+#define SQ(x)		((x) * (x))
+#define MAX(a, b)	((a) > (b) ? (a) : (b))
+#define MIN(a, b)	((a) < (b) ? (a) : (b))
+#define DOT(a, b)	((a).x * (b).x + (a).y * (b).y + (a).z * (b).z)
+#define NORMALIZE(a)  do {\
+	double len = sqrt(DOT(a, a));\
+	(a).x /= len; (a).y /= len; (a).z /= len;\
+} while(0);
+
+/* global state */
+int xres = 800;
+int yres = 600;
+int rays_per_pixel = 1;
+double aspect = 1.333333;
+struct sphere *obj_list;
+struct vec3 lights[MAX_LIGHTS];
+int lnum = 0;
+struct camera cam;
+
+int thread_num = 1;
+struct thread_data *threads;
+
+int start = 0;
+pthread_mutex_t start_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t start_cond = PTHREAD_COND_INITIALIZER;
+
+#define NRAN	1024
+#define MASK	(NRAN - 1)
+struct vec3 urand[NRAN];
+int irand[NRAN];
+
+const char *usage = {
+	"Usage: c-ray-mt [options]\n"
+	"  Reads a scene file from stdin, writes the image to stdout, and stats to stderr.\n\n"
+	"Options:\n"
+	"  -t <num>   how many threads to use (default: 1)\n"
+	"  -s WxH     where W is the width and H the height of the image\n"
+	"  -r <rays>  shoot <rays> rays per pixel (antialiasing)\n"
+	"  -i <file>  read from <file> instead of stdin\n"
+	"  -o <file>  write to <file> instead of stdout\n"
+	"  -h         this help screen\n\n"
+};
+
+
+
+int main(int argc, char **argv) {
+	int i;
+	unsigned long rend_time, start_time;
+	uint32_t *pixels;
+	double sl, sl_per_thread;
+	FILE *infile = stdin, *outfile = stdout;
+
+	for(i=1; i<argc; i++) {
+		if(argv[i][0] == '-' && argv[i][2] == 0) {
+			char *sep;
+			switch(argv[i][1]) {
+			case 't':
+				if(!isdigit(argv[++i][0])) {
+					fprintf(stderr, "-t mus be followed by the number of worker threads to spawn\n");
+					return EXIT_FAILURE;
+				}
+				thread_num = atoi(argv[i]);
+				if(!thread_num) {
+					fprintf(stderr, "invalid number of threads specified: %d\n", thread_num);
+					return EXIT_FAILURE;
+				}
+				break;
+					
+			case 's':
+				if(!isdigit(argv[++i][0]) || !(sep = strchr(argv[i], 'x')) || !isdigit(*(sep + 1))) {
+					fputs("-s must be followed by something like \"640x480\"\n", stderr);
+					return EXIT_FAILURE;
+				}
+				xres = atoi(argv[i]);
+				yres = atoi(sep + 1);
+				aspect = (double)xres / (double)yres;
+				break;
+
+			case 'i':
+				if(!(infile = fopen(argv[++i], "rb"))) {
+					fprintf(stderr, "failed to open input file %s: %s\n", argv[i], strerror(errno));
+					return EXIT_FAILURE;
+				}
+				break;
+
+			case 'o':
+				if(!(outfile = fopen(argv[++i], "wb"))) {
+					fprintf(stderr, "failed to open output file %s: %s\n", argv[i], strerror(errno));
+					return EXIT_FAILURE;
+				}
+				break;
+
+			case 'r':
+				if(!isdigit(argv[++i][0])) {
+					fputs("-r must be followed by a number (rays per pixel)\n", stderr);
+					return EXIT_FAILURE;
+				}
+				rays_per_pixel = atoi(argv[i]);
+				break;
+
+			case 'h':
+				fputs(usage, stdout);
+				return 0;
+				
+			default:
+				fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
+				fputs(usage, stderr);
+				return EXIT_FAILURE;
+			}
+		} else {
+			fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
+			fputs(usage, stderr);
+			return EXIT_FAILURE;
+		}
+	}
+
+	if(!(pixels = malloc(xres * yres * sizeof *pixels))) {
+		perror("pixel buffer allocation failed");
+		return EXIT_FAILURE;
+	}
+	load_scene(infile);
+
+	/* initialize the random number tables for the jitter */
+	for(i=0; i<NRAN; i++) urand[i].x = (double)rand() / RAND_MAX - 0.5;
+	for(i=0; i<NRAN; i++) urand[i].y = (double)rand() / RAND_MAX - 0.5;
+	for(i=0; i<NRAN; i++) irand[i] = (int)(NRAN * ((double)rand() / RAND_MAX));
+
+	if(thread_num > yres) {
+		fprintf(stderr, "more threads than scanlines specified, reducing number of threads to %d\n", yres);
+		thread_num = yres;
+	}
+
+	if(!(threads = malloc(thread_num * sizeof *threads))) {
+		perror("failed to allocate thread table");
+		return EXIT_FAILURE;
+	}
+
+	sl = 0.0;
+	sl_per_thread = (double)yres / (double)thread_num;
+	for(i=0; i<thread_num; i++) {
+		threads[i].sl_start = (int)sl;
+		sl += sl_per_thread;
+		threads[i].sl_count = (int)sl - threads[i].sl_start;
+		threads[i].pixels = pixels;
+		
+		if(pthread_create(&threads[i].tid, 0, thread_func, &threads[i]) != 0) {
+			perror("failed to spawn thread");
+			return EXIT_FAILURE;
+		}
+	}
+	threads[thread_num - 1].sl_count = yres - threads[thread_num - 1].sl_start;
+
+	fprintf(stderr, VER_STR, VER_MAJOR, VER_MINOR);
+	
+	pthread_mutex_lock(&start_mutex);
+	start_time = get_msec();
+	start = 1;
+	pthread_cond_broadcast(&start_cond);
+	pthread_mutex_unlock(&start_mutex);
+
+	for(i=0; i<thread_num; i++) {
+		pthread_join(threads[i].tid, 0);
+	}
+	rend_time = get_msec() - start_time;
+	
+	/* output statistics to stderr */
+	fprintf(stderr, "Rendering took: %lu seconds (%lu milliseconds)\n", rend_time / 1000, rend_time);
+
+	/* output the image */
+	fprintf(outfile, "P6\n%d %d\n255\n", xres, yres);
+	for(i=0; i<xres * yres; i++) {
+		fputc((pixels[i] >> RSHIFT) & 0xff, outfile);
+		fputc((pixels[i] >> GSHIFT) & 0xff, outfile);
+		fputc((pixels[i] >> BSHIFT) & 0xff, outfile);
+	}
+	fflush(outfile);
+
+	if(infile != stdin) fclose(infile);
+	if(outfile != stdout) fclose(outfile);
+	return 0;
+}
+
+/* render a frame of xsz/ysz dimensions into the provided framebuffer */
+void render_scanline(int xsz, int ysz, int sl, uint32_t *fb, int samples) {
+	int i, s;
+	double rcp_samples = 1.0 / (double)samples;
+
+	for(i=0; i<xsz; i++) {
+		double r, g, b;
+		r = g = b = 0.0;
+			
+		for(s=0; s<samples; s++) {
+			struct vec3 col = trace(get_primary_ray(i, sl, s), 0);
+			r += col.x;
+			g += col.y;
+			b += col.z;
+		}
+
+		r = r * rcp_samples;
+		g = g * rcp_samples;
+		b = b * rcp_samples;
+			
+		fb[sl * xsz + i] = ((uint32_t)(MIN(r, 1.0) * 255.0) & 0xff) << RSHIFT |
+							((uint32_t)(MIN(g, 1.0) * 255.0) & 0xff) << GSHIFT |
+							((uint32_t)(MIN(b, 1.0) * 255.0) & 0xff) << BSHIFT;
+	}
+}
+
+/* trace a ray throught the scene recursively (the recursion happens through
+ * shade() to calculate reflection rays if necessary).
+ */
+struct vec3 trace(struct ray ray, int depth) {
+	struct vec3 col;
+	struct spoint sp, nearest_sp;
+	struct sphere *nearest_obj = 0;
+	struct sphere *iter = obj_list->next;
+
+	/* if we reached the recursion limit, bail out */
+	if(depth >= MAX_RAY_DEPTH) {
+		col.x = col.y = col.z = 0.0;
+		return col;
+	}
+	
+	/* find the nearest intersection ... */
+	while(iter) {
+		if(ray_sphere(iter, ray, &sp)) {
+			if(!nearest_obj || sp.dist < nearest_sp.dist) {
+				nearest_obj = iter;
+				nearest_sp = sp;
+			}
+		}
+		iter = iter->next;
+	}
+
+	/* and perform shading calculations as needed by calling shade() */
+	if(nearest_obj) {
+		col = shade(nearest_obj, &nearest_sp, depth);
+	} else {
+		col.x = col.y = col.z = 0.0;
+	}
+
+	return col;
+}
+
+/* Calculates direct illumination with the phong reflectance model.
+ * Also handles reflections by calling trace again, if necessary.
+ */
+struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth) {
+	int i;
+	struct vec3 col = {0, 0, 0};
+
+	/* for all lights ... */
+	for(i=0; i<lnum; i++) {
+		double ispec, idiff;
+		struct vec3 ldir;
+		struct ray shadow_ray;
+		struct sphere *iter = obj_list->next;
+		int in_shadow = 0;
+
+		ldir.x = lights[i].x - sp->pos.x;
+		ldir.y = lights[i].y - sp->pos.y;
+		ldir.z = lights[i].z - sp->pos.z;
+
+		shadow_ray.orig = sp->pos;
+		shadow_ray.dir = ldir;
+
+		/* shoot shadow rays to determine if we have a line of sight with the light */
+		while(iter) {
+			if(ray_sphere(iter, shadow_ray, 0)) {
+				in_shadow = 1;
+				break;
+			}
+			iter = iter->next;
+		}
+
+		/* and if we're not in shadow, calculate direct illumination with the phong model. */
+		if(!in_shadow) {
+			NORMALIZE(ldir);
+
+			idiff = MAX(DOT(sp->normal, ldir), 0.0);
+			ispec = obj->mat.spow > 0.0 ? pow(MAX(DOT(sp->vref, ldir), 0.0), obj->mat.spow) : 0.0;
+
+			col.x += idiff * obj->mat.col.x + ispec;
+			col.y += idiff * obj->mat.col.y + ispec;
+			col.z += idiff * obj->mat.col.z + ispec;
+		}
+	}
+
+	/* Also, if the object is reflective, spawn a reflection ray, and call trace()
+	 * to calculate the light arriving from the mirror direction.
+	 */
+	if(obj->mat.refl > 0.0) {
+		struct ray ray;
+		struct vec3 rcol;
+
+		ray.orig = sp->pos;
+		ray.dir = sp->vref;
+		ray.dir.x *= RAY_MAG;
+		ray.dir.y *= RAY_MAG;
+		ray.dir.z *= RAY_MAG;
+
+		rcol = trace(ray, depth + 1);
+		col.x += rcol.x * obj->mat.refl;
+		col.y += rcol.y * obj->mat.refl;
+		col.z += rcol.z * obj->mat.refl;
+	}
+
+	return col;
+}
+
+/* calculate reflection vector */
+struct vec3 reflect(struct vec3 v, struct vec3 n) {
+	struct vec3 res;
+	double dot = v.x * n.x + v.y * n.y + v.z * n.z;
+	res.x = -(2.0 * dot * n.x - v.x);
+	res.y = -(2.0 * dot * n.y - v.y);
+	res.z = -(2.0 * dot * n.z - v.z);
+	return res;
+}
+
+struct vec3 cross_product(struct vec3 v1, struct vec3 v2) {
+	struct vec3 res;
+	res.x = v1.y * v2.z - v1.z * v2.y;
+	res.y = v1.z * v2.x - v1.x * v2.z;
+	res.z = v1.x * v2.y - v1.y * v2.x;
+	return res;
+}
+
+/* determine the primary ray corresponding to the specified pixel (x, y) */
+struct ray get_primary_ray(int x, int y, int sample) {
+	struct ray ray;
+	float m[3][3];
+	struct vec3 i, j = {0, 1, 0}, k, dir, orig, foo;
+
+	k.x = cam.targ.x - cam.pos.x;
+	k.y = cam.targ.y - cam.pos.y;
+	k.z = cam.targ.z - cam.pos.z;
+	NORMALIZE(k);
+
+	i = cross_product(j, k);
+	j = cross_product(k, i);
+	m[0][0] = i.x; m[0][1] = j.x; m[0][2] = k.x;
+	m[1][0] = i.y; m[1][1] = j.y; m[1][2] = k.y;
+	m[2][0] = i.z; m[2][1] = j.z; m[2][2] = k.z;
+	
+	ray.orig.x = ray.orig.y = ray.orig.z = 0.0;
+	ray.dir = get_sample_pos(x, y, sample);
+	ray.dir.z = 1.0 / HALF_FOV;
+	ray.dir.x *= RAY_MAG;
+	ray.dir.y *= RAY_MAG;
+	ray.dir.z *= RAY_MAG;
+	
+	dir.x = ray.dir.x + ray.orig.x;
+	dir.y = ray.dir.y + ray.orig.y;
+	dir.z = ray.dir.z + ray.orig.z;
+	foo.x = dir.x * m[0][0] + dir.y * m[0][1] + dir.z * m[0][2];
+	foo.y = dir.x * m[1][0] + dir.y * m[1][1] + dir.z * m[1][2];
+	foo.z = dir.x * m[2][0] + dir.y * m[2][1] + dir.z * m[2][2];
+
+	orig.x = ray.orig.x * m[0][0] + ray.orig.y * m[0][1] + ray.orig.z * m[0][2] + cam.pos.x;
+	orig.y = ray.orig.x * m[1][0] + ray.orig.y * m[1][1] + ray.orig.z * m[1][2] + cam.pos.y;
+	orig.z = ray.orig.x * m[2][0] + ray.orig.y * m[2][1] + ray.orig.z * m[2][2] + cam.pos.z;
+
+	ray.orig = orig;
+	ray.dir.x = foo.x + orig.x;
+	ray.dir.y = foo.y + orig.y;
+	ray.dir.z = foo.z + orig.z;
+	
+	return ray;
+}
+
+
+struct vec3 get_sample_pos(int x, int y, int sample) {
+	struct vec3 pt;
+	static double sf = 0.0;
+
+	if(sf == 0.0) {
+		sf = 1.5 / (double)xres;
+	}
+
+	pt.x = ((double)x / (double)xres) - 0.5;
+	pt.y = -(((double)y / (double)yres) - 0.65) / aspect;
+
+	if(sample) {
+		struct vec3 jt = jitter(x, y, sample);
+		pt.x += jt.x * sf;
+		pt.y += jt.y * sf / aspect;
+	}
+	return pt;
+}
+
+/* jitter function taken from Graphics Gems I. */
+struct vec3 jitter(int x, int y, int s) {
+	struct vec3 pt;
+	pt.x = urand[(x + (y << 2) + irand[(x + s) & MASK]) & MASK].x;
+	pt.y = urand[(y + (x << 2) + irand[(y + s) & MASK]) & MASK].y;
+	return pt;
+}
+
+/* Calculate ray-sphere intersection, and return {1, 0} to signify hit or no hit.
+ * Also the surface point parameters like position, normal, etc are returned through
+ * the sp pointer if it is not NULL.
+ */
+int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp) {
+	double a, b, c, d, sqrt_d, t1, t2;
+	
+	a = SQ(ray.dir.x) + SQ(ray.dir.y) + SQ(ray.dir.z);
+	b = 2.0 * ray.dir.x * (ray.orig.x - sph->pos.x) +
+				2.0 * ray.dir.y * (ray.orig.y - sph->pos.y) +
+				2.0 * ray.dir.z * (ray.orig.z - sph->pos.z);
+	c = SQ(sph->pos.x) + SQ(sph->pos.y) + SQ(sph->pos.z) +
+				SQ(ray.orig.x) + SQ(ray.orig.y) + SQ(ray.orig.z) +
+				2.0 * (-sph->pos.x * ray.orig.x - sph->pos.y * ray.orig.y - sph->pos.z * ray.orig.z) - SQ(sph->rad);
+	
+	if((d = SQ(b) - 4.0 * a * c) < 0.0) return 0;
+
+	sqrt_d = sqrt(d);
+	t1 = (-b + sqrt_d) / (2.0 * a);
+	t2 = (-b - sqrt_d) / (2.0 * a);
+
+	if((t1 < ERR_MARGIN && t2 < ERR_MARGIN) || (t1 > 1.0 && t2 > 1.0)) return 0;
+
+	if(sp) {
+		if(t1 < ERR_MARGIN) t1 = t2;
+		if(t2 < ERR_MARGIN) t2 = t1;
+		sp->dist = t1 < t2 ? t1 : t2;
+		
+		sp->pos.x = ray.orig.x + ray.dir.x * sp->dist;
+		sp->pos.y = ray.orig.y + ray.dir.y * sp->dist;
+		sp->pos.z = ray.orig.z + ray.dir.z * sp->dist;
+		
+		sp->normal.x = (sp->pos.x - sph->pos.x) / sph->rad;
+		sp->normal.y = (sp->pos.y - sph->pos.y) / sph->rad;
+		sp->normal.z = (sp->pos.z - sph->pos.z) / sph->rad;
+
+		sp->vref = reflect(ray.dir, sp->normal);
+		NORMALIZE(sp->vref);
+	}
+	return 1;
+}
+
+/* Load the scene from an extremely simple scene description file */
+#define DELIM	" \t\n"
+void load_scene(FILE *fp) {
+	char line[256], *ptr, type;
+
+	obj_list = malloc(sizeof(struct sphere));
+	obj_list->next = 0;
+	
+	while((ptr = fgets(line, 256, fp))) {
+		int i;
+		struct vec3 pos, col;
+		double rad, spow, refl;
+		
+		while(*ptr == ' ' || *ptr == '\t') ptr++;
+		if(*ptr == '#' || *ptr == '\n') continue;
+
+		if(!(ptr = strtok(line, DELIM))) continue;
+		type = *ptr;
+		
+		for(i=0; i<3; i++) {
+			if(!(ptr = strtok(0, DELIM))) break;
+			*((double*)&pos.x + i) = atof(ptr);
+		}
+
+		if(type == 'l') {
+			lights[lnum++] = pos;
+			continue;
+		}
+
+		if(!(ptr = strtok(0, DELIM))) continue;
+		rad = atof(ptr);
+
+		for(i=0; i<3; i++) {
+			if(!(ptr = strtok(0, DELIM))) break;
+			*((double*)&col.x + i) = atof(ptr);
+		}
+
+		if(type == 'c') {
+			cam.pos = pos;
+			cam.targ = col;
+			cam.fov = rad;
+			continue;
+		}
+
+		if(!(ptr = strtok(0, DELIM))) continue;
+		spow = atof(ptr);
+
+		if(!(ptr = strtok(0, DELIM))) continue;
+		refl = atof(ptr);
+
+		if(type == 's') {
+			struct sphere *sph = malloc(sizeof *sph);
+			sph->next = obj_list->next;
+			obj_list->next = sph;
+
+			sph->pos = pos;
+			sph->rad = rad;
+			sph->mat.col = col;
+			sph->mat.spow = spow;
+			sph->mat.refl = refl;
+		} else {
+			fprintf(stderr, "unknown type: %c\n", type);
+		}
+	}
+}
+
+
+/* provide a millisecond-resolution timer for each system */
+#if defined(unix) || defined(__unix__)
+#include <time.h>
+#include <sys/time.h>
+unsigned long get_msec(void) {
+	static struct timeval timeval, first_timeval;
+	
+	gettimeofday(&timeval, 0);
+	if(first_timeval.tv_sec == 0) {
+		first_timeval = timeval;
+		return 0;
+	}
+	return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000;
+}
+#elif defined(__WIN32__) || defined(WIN32)
+#include <windows.h>
+unsigned long get_msec(void) {
+	return GetTickCount();
+}
+#else
+#error "I don't know how to measure time on your platform"
+#endif
+
+void *thread_func(void *tdata) {
+	int i;
+	struct thread_data *td = (struct thread_data*)tdata;
+
+	pthread_mutex_lock(&start_mutex);
+	while(!start) {
+		pthread_cond_wait(&start_cond, &start_mutex);
+	}
+	pthread_mutex_unlock(&start_mutex);
+
+	for(i=0; i<td->sl_count; i++) {
+		render_scanline(xres, yres, i + td->sl_start, td->pixels, rays_per_pixel);
+	}
+
+	return 0;
+}

Added: demo/xsede.2014.0425/src/c-ray/scene.cr
===================================================================
--- demo/xsede.2014.0425/src/c-ray/scene.cr	                        (rev 0)
+++ demo/xsede.2014.0425/src/c-ray/scene.cr	2014-04-24 17:50:23 UTC (rev 7793)
@@ -0,0 +1,18 @@
+# spheres
+#	position		radius	color			shininess	reflectivity
+s	-1.5 -0.3 -1	0.7		1.0 0.2 0.05		50.0	0.3
+s	1.5 -0.4 0		0.6		0.1 0.85 1.0		50.0	0.4
+
+# walls
+s	0 -1000 2		999		0.1 0.2 0.6			80.0	0.8
+
+# bouncing ball
+s	0 0 2			1		1.0 0.5 0.1			60.0	0.7
+
+# lights...
+l	-50 100 -50
+l	40 40 150
+
+# camera (there can be only one!)
+#	position	FOV		target
+c	0 6 -17		45		0 -1 0

Added: demo/xsede.2014.0425/src/c-ray/sphfract.cr
===================================================================
--- demo/xsede.2014.0425/src/c-ray/sphfract.cr	                        (rev 0)
+++ demo/xsede.2014.0425/src/c-ray/sphfract.cr	2014-04-24 17:50:23 UTC (rev 7793)
@@ -0,0 +1,192 @@
+s	0 0 0 	1.0	0.25 0.25 0.25  50.0	0.65
+s	1.4 0 0 	0.4	0.25 0.25 0.25  50.0	0.65
+s	1.96 0 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	2.184 0 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.96 0.224 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.96 -0.224 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.96 0 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.96 0 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0.56 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	1.624 0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.176 0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0.784 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0.56 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0.56 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 -0.56 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	1.624 -0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.176 -0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 -0.784 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 -0.56 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 -0.56 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0 0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	1.624 0 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.176 0 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0.224 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 -0.224 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0 0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0 -0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	1.624 0 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.176 0 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0.224 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 -0.224 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	1.4 0 -0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0 0 	0.4	0.25 0.25 0.25  50.0	0.65
+s	-1.96 0 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-2.184 0 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.96 0.224 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.96 -0.224 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.96 0 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.96 0 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0.56 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-1.176 0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.624 0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0.784 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0.56 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0.56 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 -0.56 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-1.176 -0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.624 -0.56 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 -0.784 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 -0.56 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 -0.56 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0 0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-1.176 0 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.624 0 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0.224 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 -0.224 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0 0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0 -0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-1.176 0 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.624 0 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0.224 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 -0.224 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-1.4 0 -0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.4 0 	0.4	0.25 0.25 0.25  50.0	0.65
+s	0.56 1.4 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.784 1.4 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 1.624 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 1.176 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 1.4 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 1.4 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 1.4 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-0.784 1.4 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 1.624 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 1.176 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 1.4 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 1.4 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.96 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 1.96 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 1.96 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 2.184 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.96 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.96 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.4 0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 1.4 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 1.4 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.624 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.176 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.4 0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.4 -0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 1.4 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 1.4 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.624 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.176 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 1.4 -0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.4 0 	0.4	0.25 0.25 0.25  50.0	0.65
+s	0.56 -1.4 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.784 -1.4 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 -1.176 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 -1.624 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 -1.4 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 -1.4 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 -1.4 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-0.784 -1.4 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 -1.176 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 -1.624 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 -1.4 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 -1.4 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.96 0 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 -1.96 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 -1.96 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -2.184 0 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.96 0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.96 -0.224 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.4 0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 -1.4 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 -1.4 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.176 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.624 0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.4 0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.4 -0.56 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 -1.4 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 -1.4 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.176 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.624 -0.56 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -1.4 -0.784 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0 1.4 	0.4	0.25 0.25 0.25  50.0	0.65
+s	0.56 0 1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.784 0 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 0.224 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 -0.224 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 0 1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 0 1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0 1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-0.784 0 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0.224 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 -0.224 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0 1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0 1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.56 1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 0.56 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 0.56 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.784 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.56 1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.56 1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.56 1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 -0.56 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 -0.56 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.784 1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.56 1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.56 1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0 1.96 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 0 1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 0 1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.224 1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.224 1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0 2.184 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0 -1.4 	0.4	0.25 0.25 0.25  50.0	0.65
+s	0.56 0 -1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.784 0 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 0.224 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 -0.224 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 0 -1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0.56 0 -1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0 -1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	-0.784 0 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0.224 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 -0.224 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0 -1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.56 0 -1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.56 -1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 0.56 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 0.56 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.784 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.56 -1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.56 -1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.56 -1.4 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 -0.56 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 -0.56 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.784 -1.4 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.56 -1.176 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.56 -1.624 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0 -1.96 	0.16	0.25 0.25 0.25  50.0	0.65
+s	0.224 0 -1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	-0.224 0 -1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0.224 -1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 -0.224 -1.96 	0.064	0.25 0.25 0.25  50.0	0.65
+s	0 0 -2.184 	0.064	0.25 0.25 0.25  50.0	0.65
+s  0 -10002.25 0  10000  0.2 0.35 0.5  80.0  0.4
+s  0  10100.00 0  10000  0.5 0.2 0.1  40.0  0.0
+l	-50 68 -50
+l	40 40 150
+c	-7 6 -12 45  0 -0.65 0




More information about the Swift-commit mailing list