Index: bn_poly.c
===================================================================
--- bn_poly.c	(revision 0)
+++ bn_poly.c	(revision 0)
@@ -0,0 +1,226 @@
+/*                          B N _ P O L Y . C
+ * BRL-CAD
+ *
+ * Copyright (c) 2012 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+
+#include "common.h"
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "bu.h"
+#include "vmath.h"
+#include "bn.h"
+ /*
+ * FORMAT:
+ * TestType 0,0,0,0,0,0  0,0,0,0,0,0  0,0,0,0,0,0  0,0,0,0,0,0
+ */
+int
+test_synthetic(struct bn_poly *poly_dvsor, struct bn_poly *poly_dvdend, struct bn_poly *exact_quo, struct bn_poly *exact_rem)
+{
+    /* quotient and remainder of sythetic division to test answer */
+    struct bn_poly poly_quo;
+    struct bn_poly poly_rem;
+    unsigned i;
+    /* call sythetic division, begin checking expected and actual answer for errors */
+    bn_poly_synthetic_division(&poly_quo, &poly_rem, poly_dvdend, poly_dvsor);
+    for (i = 0; i < (poly_quo.dgr + 1); i++) {
+            /* if any coefficients are off, return with a bad call */
+        if (!EQUAL(poly_quo.cf[i], exact_quo->cf[i]) || !EQUAL(poly_rem.cf[i], exact_rem->cf[i])) {
+            bu_log("Synthetic division failed! coefficients not equal...\n");
+            return 1;
+        }
+
+    }
+    /* everything went as expected... */
+    return 0;
+}
+
+int
+test_mult(struct bn_poly *poly_eqn, struct bn_poly *poly_mul, struct bn_poly *exact_ans)
+{
+    struct bn_poly poly_summ;
+    unsigned i;
+    /* test multiplication and begin checking data */
+    poly_summ = *(bn_poly_mul(&poly_summ,poly_eqn, poly_mul));
+    if (poly_summ.dgr != exact_ans->dgr)
+        return 1;
+    else {
+        for (i = 0; i < (poly_summ.dgr + 1); i++) {
+            if (!EQUAL(poly_summ.cf[i], exact_ans->cf[i])) {
+                bu_log("Multiplication failed! coefficients not equal...\n");
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+int
+test_scale(struct bn_poly *poly_scale, struct bn_poly *exact_quo)
+{
+    unsigned i;
+    /* scale by a constant factor */
+    *poly_scale = *(bn_poly_scale(poly_scale,2));
+    for (i = 0; i < (poly_scale->dgr +1); i++) {
+        if (!EQUAL(poly_scale->cf[i], exact_quo->cf[i])) {
+            return 1;
+            bu_log("Scaling failed! coefficients not equal...\n");
+        }
+    }
+    return 0;
+}
+
+int
+test_add_sub(struct bn_poly *poly_eqn1, struct bn_poly *poly_eqn2, struct bn_poly *exact_ans_add, struct bn_poly *exact_ans_sub)
+{
+    /* sum to be used for functions, loop iterator i for checking data */
+    struct bn_poly poly_sum;
+    unsigned i;
+    /* test addition */
+    poly_sum = *(bn_poly_add(&poly_sum, poly_eqn1, poly_eqn2));
+    for (i = 0; i < (poly_sum.dgr +1);i++) {
+        if (!EQUAL(poly_sum.cf[i], exact_ans_add->cf[i])) {
+            bu_log("Addition failed! coefficients not equal...\n");
+            return 1;
+        }
+    }
+
+    /* test subtraction */
+    poly_sum = *(bn_poly_sub(&poly_sum, poly_eqn1, poly_eqn2));
+    for (i = 0; i < (poly_sum.dgr +1); i++) {
+        if (!EQUAL(poly_sum.cf[i], exact_ans_sub->cf[i])) {
+            bu_log("Subtraction failed! coefficients not equal...\n");
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+int
+test_roots(struct bn_poly *poly_eqn, struct bn_complex *exact_roots)
+{
+    /* size of roots will depend on degree given */
+    struct bn_complex *roots;
+    int canbesolved;
+    int i,k,rootmatch;
+    roots = (struct bn_complex*)bu_malloc(sizeof(struct bn_complex) * poly_eqn->dgr, "PolynomialRoots");
+
+    /* if equation is a quadratic */
+    if (poly_eqn->dgr == 2) {
+        canbesolved = bn_poly_quadratic_roots(roots, poly_eqn);
+        if (canbesolved == 0)
+            bu_log("Quadratic roots do not exist, polynomial cannot be solved!\n");
+    }
+	 /* if equation is cubic */
+    if (poly_eqn->dgr == 3) {
+        canbesolved = bn_poly_cubic_roots(roots, poly_eqn);
+        if (canbesolved == 0)
+            bu_log("Cubic roots do not exist, polynomial cannot be solved!\n");
+    }
+    /* if equation is quartic */
+    if (poly_eqn->dgr == 4) {
+        canbesolved = bn_poly_quartic_roots(roots, poly_eqn);
+        if (canbesolved == 0)
+            bu_log("Quartic roots do not exist, polynomial cannot be solved!\n");
+    }
+
+    rootmatch =0;
+    /* run through roots, checking if any roots are equal to each other and adding accordingly */
+    for (k = 0; k < (int)(sizeof(roots) / sizeof(struct bn_complex)); k++) {
+        for ( i =0; i < (int)(sizeof(exact_roots) / sizeof(struct bn_complex)); i++) {
+            if (EQUAL(roots[k].re, exact_roots[i].re) && EQUAL(roots[k].im, exact_roots[i].im))
+                rootmatch++;
+        }
+    }
+    bu_free(roots, "Freeing Roots memory");
+    /* if the number of matching roots is equal to the number of roots */
+    if (rootmatch >= (int)poly_eqn->dgr)
+        return 0;
+    return 1;
+
+}
+
+void swap(double *fp, double *sp)
+{
+    double temp;
+    temp = *fp;
+    *fp = *sp;
+    *sp = temp;
+}
+
+/*
+ * FORMAT FOR ROOTS
+ * TYPE 0,0,0,0,0,0  0,0  0,0  0,0  0,0
+ */
+int
+main(int argc, char *argv[])
+{
+    /* two equations, two answers used to test functions, undeclared readroots to allocate memory only if readroots is used */
+    struct bn_poly poly_eqn1;
+    struct bn_poly poly_eqn2;
+    struct bn_poly poly_exact_ans;
+    struct bn_poly poly_ex_ans;
+    struct bn_complex *readroots;
+    unsigned counter;
+    if (argc < 3){
+        bu_log("Invalid paramters!\n");
+        return 1;
+    }
+
+    /* read input from format given to command line */
+    sscanf(argv[2], "%u,%lf,%lf,%lf,%lf,%lf", &poly_eqn1.dgr, &poly_eqn1.cf[4], &poly_eqn1.cf[3], &poly_eqn1.cf[2], &poly_eqn1.cf[1], &poly_eqn1.cf[0]);
+    /* root test gets a new format for numbers(different from other tests) */
+    if (bu_strcmp(argv[1],"rt") == 0) {
+        readroots = (struct bn_complex*)bu_malloc(sizeof(struct bn_complex)*4, "main Roots");
+        sscanf(argv[3], "%lf,%lf", &readroots[3].re, &readroots[3].im);
+        sscanf(argv[4], "%lf,%lf", &readroots[2].re, &readroots[2].im);
+        sscanf(argv[5], "%lf,%lf", &readroots[1].re, &readroots[1].im);
+        sscanf(argv[6], "%lf,%lf", &readroots[0].re, &readroots[0].im);
+    /* use default format if roots is not the format to be tested */
+    } else {
+        sscanf(argv[3], "%u,%lf,%lf,%lf,%lf,%lf", &poly_eqn2.dgr, &poly_eqn2.cf[4], &poly_eqn2.cf[3],&poly_eqn2.cf[2], &poly_eqn2.cf[1], &poly_eqn2.cf[0]);
+        sscanf(argv[4], "%u,%lf,%lf,%lf,%lf,%lf", &poly_exact_ans.dgr, &poly_exact_ans.cf[4], &poly_exact_ans.cf[3], &poly_exact_ans.cf[2], &poly_exact_ans.cf[1], &poly_exact_ans.cf[0]);
+        sscanf(argv[5], "%u,%lf,%lf,%lf,%lf,%lf", &poly_ex_ans.dgr, &poly_ex_ans.cf[4], &poly_ex_ans.cf[3], &poly_ex_ans.cf[2], &poly_ex_ans.cf[1], &poly_ex_ans.cf[0]);
+    }
+    /* reverse data held to properly support functions */
+    for (counter = 0; counter < ((poly_eqn1.dgr+1)/2); counter++)
+        swap(&poly_eqn1.cf[counter], &poly_eqn1.cf[poly_eqn1.dgr -(int)counter]);
+    for (counter = 0; counter < ((poly_eqn2.dgr+1)/2); counter++)
+        swap(&poly_eqn2.cf[counter], &poly_eqn2.cf[poly_eqn2.dgr -(int)counter]);
+    for (counter = 0; counter < ((poly_exact_ans.dgr+1)/2); counter++)
+        swap(&poly_exact_ans.cf[counter], &poly_exact_ans.cf[poly_exact_ans.dgr - (int)counter]);
+
+    /* synthetic division */
+    if (bu_strcmp(argv[1],"sd") == 0) {
+        return test_synthetic(&poly_eqn1, &poly_eqn2, &poly_exact_ans, &poly_ex_ans);
+    }
+	 /* basic operations(add/sub) */
+    if (bu_strcmp(argv[1],"bo") == 0) {
+	     return test_add_sub(&poly_eqn1, &poly_eqn2, &poly_exact_ans, &poly_ex_ans);
+    }
+    /* multiplication */
+    if (bu_strcmp(argv[1],"mu") == 0) {
+        return test_mult(&poly_eqn1, &poly_eqn2, &poly_exact_ans);
+    }
+    /* scale */
+    if (bu_strcmp(argv[1],"sc") == 0) {
+        return test_scale(&poly_eqn1, &poly_exact_ans);
+    }
+    /* roots */
+    if (bu_strcmp(argv[1],"rt") == 0) {
+        counter = test_roots(&poly_eqn1, readroots);
+        bu_free(readroots,"main Roots freed");
+        return (int)counter;
+    }
+    return 1;
+}
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 54112)
+++ CMakeLists.txt	(working copy)
@@ -1,6 +1,7 @@
 BRLCAD_ADDEXEC(tester_bn_coplanar_tri_tri_isect bn_coplanar_tri_tri_isect.c "libbu;libbn" NO_INSTALL LOCAL)
 BRLCAD_ADDEXEC(tester_bn_tri_tri_isect bn_tri_tri_isect.c "libbu;libbn" NO_INSTALL LOCAL)
 BRLCAD_ADDEXEC(tester_bn_list bn_list.c "libbu;libbn" NO_INSTALL LOCAL)
+BRLCAD_ADDEXEC(tester_bn_poly bn_poly.c "libbu;libbn" NO_INSTALL LOCAL)
 
 # For tester_bn_coplanar_tri_tri_isect, the input format is as follows:
 #
@@ -58,9 +59,30 @@
 add_test(bn_list_3d_3                   tester_bn_list  3  3,7,8 1,-5,8)
 add_test(bn_list_3d_4                   tester_bn_list  3  3,7,8 1,-5.321,3 67,0,67 0,100,23)
 
+#
+#   ************ poly.c tests *************
+#
+# Format is:
+
+# NORMAL:
+# tester_bn_poly exe <type> <polynomial1> <polynomial2> <exactPolynomial1> <extraExactPolynomial2>
+# Where <type> sd(synth division) bo(add/subtract) mu(multiply) sc(scale) rt(roots)
+# Polynomials are entered in the format degree,ix^4,ix^3,ix^2,ix,i -> 0,0,0,0,0,0
+# ROOT:
+# tester_bn_poly exe rt <polynomial1> <complexroot1> <complexroot2> <complexroot3> <complexroot4>
+# Where complexroots are entered in the format re,im -> 0,0
+add_test(bn_poly_scale                  tester_bn_poly sc   2,0,0,3,6,4      0,0,0,0,0,0      2,0,0,6,12,8      0,0,0,0,0,0)
+add_test(bn_poly_mult                   tester_bn_poly mu   1,0,0,0,3,2      2,0,0,5,2,3      3,0,15,16,13,6    0,0,0,0,0,0)
+add_test(bn_poly_add_sub                tester_bn_poly bo   2,0,0,6,3,4      1,0,0,0,3,2      2,0,0,6,6,6       2,0,0,6,0,2)
+add_test(bn_poly_synthetic_division     tester_bn_poly sd   1,0,0,0,1,-2     3,0,1,-5,2,8     2,0,0,1,-3,-4     0,0,0,0,0,0)
+add_test(bn_poly_roots_quad             tester_bn_poly rt   2,0,0,1,-1,-6    0,0              0,0               3,0          -2,0)
+add_test(bn_poly_root_cubic             tester_bn_poly rt   3,0,1,8,9,18     0,0              3,0              -1,0           6,0)
+add_test(bn_poly_root_quartic           tester_bn_poly rt   4,1,-9,17,9,-18  1,0              3,0              -1,0           6,0)
+
+
 # Local Variables:
 # tab-width: 8
 # mode: cmake
 # indent-tabs-mode: t
 # End:
-# ex: shiftwidth=2 tabstop=8 textwidth=0 wrapmargin=0
+# ex: shiftwidth=2 tabstop=8 textwidth=0 wrapmargin=0
\ No newline at end of file
