#!/bin/bash
#
# @file:
#   gen_factoring.sh
#
# @description:
#   Generate the factoring device.
# This script emits Java code for factoring
# 32bit integers of the form n = p * q, where
# p and q are divisors of n.
#
# @author:
#   Roger G. Doss
#

M=256;
COUNT=0;
OUTPUT="gfactor.java"
if [ -e $OUTPUT ]
then
    rm -f $OUTPUT
fi
#
# Output the preamble.
#
printf "\t/* Copyright (C) Roger G. Doss.  All rights reserved. */\n" >> $OUTPUT
printf "\t/* Code generated on $DATE */\n" >> $OUTPUT
printf "\timport java.*;\n" >> $OUTPUT
printf "\tpublic class gfactor {\n" >> $OUTPUT
printf "\tpublic gfactor(long n)\n" >> $OUTPUT
printf "\t{\n" >> $OUTPUT
printf "\t\t__do_factor(n); \n" >> $OUTPUT
printf "\t}\n" >> $OUTPUT
printf "\tpublic void __do_factor(long n)\n" >> $OUTPUT
printf "\t{\n" >> $OUTPUT
printf "      if(n == 1 || n == 0) { System.out.println(n); }\n" >> $OUTPUT
printf "      if((n %% 2) == 0) {\n" >> $OUTPUT
printf "         System.out.println(\"factored: p: 2 \" + \" q: \" + n/2);\n" >> $OUTPUT
printf "         return;\n" >> $OUTPUT
printf "      }\n" >> $OUTPUT
printf "      long bound = (long)Math.ceil(Math.sqrt(n));\n" >> $OUTPUT
printf "      int m = $M;\n" >> $OUTPUT
printf "      long limit = (long)Math.ceil(bound/m);\n" >> $OUTPUT
printf "      if(limit == 0) { limit = 1; }\n" >> $OUTPUT
printf "      long k[] = new long[m];\n" >> $OUTPUT
printf "      k[0]=3;\n" >> $OUTPUT
printf "      for(int i = 1; i < m; i++) {\n" >> $OUTPUT
printf "        k[i]=k[i-1]+limit;\n" >> $OUTPUT
printf "      }\n" >> $OUTPUT
printf "      while(true) {\n" >> $OUTPUT
printf "\n" >> $OUTPUT
#
# Generate the test branches up to M.
#
while [ $M != 0 ]
do
    printf "        if((n %% k[$COUNT]++ ) == 0) {\n" >> $OUTPUT
    printf "            System.out.println(\"[$COUNT] factored: p: \" +  n/--k[$COUNT] + \" q: \" + k[$COUNT]);\n" >> $OUTPUT
    printf "            break;\n" >> $OUTPUT
    printf "        }\n" >> $OUTPUT
    ((COUNT=$COUNT + 1));
    ((M=$M - 1));
done
#
# Terminate the device.
#
((COUNT=$COUNT-1));
printf "        if(k[$COUNT] > bound) {\n" >> $OUTPUT
printf "            System.out.println(\"prime: \" + n);\n" >> $OUTPUT
printf "            break;\n" >> $OUTPUT
printf "        }\n" >> $OUTPUT
printf "      }\n" >> $OUTPUT
printf "   }\n" >> $OUTPUT
#
# Output main.
#
printf "    public static void main(String[] args)\n" >> $OUTPUT
printf "    {\n" >> $OUTPUT
printf "        try {\n" >> $OUTPUT
printf "            long i = Integer.parseInt(args[0].trim());\n" >> $OUTPUT
printf "            System.out.println(\"factoring: \" + i);\n" >> $OUTPUT
printf "            gfactor _1 = new gfactor(i);\n" >> $OUTPUT
printf "        } catch (NumberFormatException nfe) {\n" >> $OUTPUT
printf "            System.out.println(\"NumberFormatException: \" + nfe.getMessage());\n" >> $OUTPUT
printf "        }\n" >> $OUTPUT
printf "    }\n" >> $OUTPUT
printf "  }\n" >> $OUTPUT
#
# EOF
#