1 2 /* 3 * M_APM - mapm5sin.c 4 * 5 * Copyright (C) 1999 - 2007 Michael C. Ring 6 * 7 * Permission to use, copy, and distribute this software and its 8 * documentation for any purpose with or without fee is hereby granted, 9 * provided that the above copyright notice appear in all copies and 10 * that both that copyright notice and this permission notice appear 11 * in supporting documentation. 12 * 13 * Permission to modify the software is granted. Permission to distribute 14 * the modified code is granted. Modifications are to be distributed by 15 * using the file 'license.txt' as a template to modify the file header. 16 * 'license.txt' is available in the official MAPM distribution. 17 * 18 * This software is provided "as is" without express or implied warranty. 19 */ 20 21 /* 22 * $Id: mapm5sin.c,v 1.10 2007/12/03 01:26:16 mike Exp $ 23 * 24 * This file contains the functions that implement the sin (5x) 25 * and cos (4x) multiple angle relations 26 * 27 * $Log: mapm5sin.c,v $ 28 * Revision 1.10 2007/12/03 01:26:16 mike 29 * Update license 30 * 31 * Revision 1.9 2002/11/03 21:50:36 mike 32 * Updated function parameters to use the modern style 33 * 34 * Revision 1.8 2001/03/25 20:57:03 mike 35 * move cos_to_sin func in here 36 * 37 * Revision 1.7 2000/05/04 23:50:21 mike 38 * use multiple angle identity 4 times of larger COS angles 39 * 40 * Revision 1.6 1999/06/30 00:08:53 mike 41 * pass more decimal places to raw functions 42 * 43 * Revision 1.5 1999/06/20 23:41:32 mike 44 * changed COS to use 4x multiple angle identity instead of 5x 45 * 46 * Revision 1.4 1999/06/20 19:42:26 mike 47 * tweak number of dec places passed to sub-functions 48 * 49 * Revision 1.3 1999/06/20 19:03:56 mike 50 * changed local static variables to MAPM stack variables 51 * 52 * Revision 1.2 1999/05/12 21:30:09 mike 53 * replace local 5.0 with global 54 * 55 * Revision 1.1 1999/05/10 20:56:31 mike 56 * Initial revision 57 */ 58 59 #include "m_apm_lc.h" 60 61 /****************************************************************************/ 62 void M_5x_sin(M_APM r, int places, M_APM x) 63 { 64 M_APM tmp8, tmp9; 65 66 tmp8 = M_get_stack_var(); 67 tmp9 = M_get_stack_var(); 68 69 m_apm_multiply(tmp9, x, MM_5x_125R); /* 1 / (5*5*5) */ 70 M_raw_sin(tmp8, (places + 6), tmp9); 71 M_5x_do_it(tmp9, (places + 4), tmp8); 72 M_5x_do_it(tmp8, (places + 4), tmp9); 73 M_5x_do_it(r, places, tmp8); 74 75 M_restore_stack(2); 76 } 77 /****************************************************************************/ 78 void M_4x_cos(M_APM r, int places, M_APM x) 79 { 80 M_APM tmp8, tmp9; 81 82 tmp8 = M_get_stack_var(); 83 tmp9 = M_get_stack_var(); 84 85 /* 86 * if |x| >= 1.0 use multiple angle identity 4 times 87 * if |x| < 1.0 use multiple angle identity 3 times 88 */ 89 90 if (x->m_apm_exponent > 0) 91 { 92 m_apm_multiply(tmp9, x, MM_5x_256R); /* 1 / (4*4*4*4) */ 93 M_raw_cos(tmp8, (places + 8), tmp9); 94 M_4x_do_it(tmp9, (places + 8), tmp8); 95 M_4x_do_it(tmp8, (places + 6), tmp9); 96 M_4x_do_it(tmp9, (places + 4), tmp8); 97 M_4x_do_it(r, places, tmp9); 98 } 99 else 100 { 101 m_apm_multiply(tmp9, x, MM_5x_64R); /* 1 / (4*4*4) */ 102 M_raw_cos(tmp8, (places + 6), tmp9); 103 M_4x_do_it(tmp9, (places + 4), tmp8); 104 M_4x_do_it(tmp8, (places + 4), tmp9); 105 M_4x_do_it(r, places, tmp8); 106 } 107 108 M_restore_stack(2); 109 } 110 /****************************************************************************/ 111 /* 112 * calculate the multiple angle identity for sin (5x) 113 * 114 * sin (5x) == 16 * sin^5 (x) - 20 * sin^3 (x) + 5 * sin(x) 115 */ 116 void M_5x_do_it(M_APM rr, int places, M_APM xx) 117 { 118 M_APM tmp0, tmp1, t2, t3, t5; 119 120 tmp0 = M_get_stack_var(); 121 tmp1 = M_get_stack_var(); 122 t2 = M_get_stack_var(); 123 t3 = M_get_stack_var(); 124 t5 = M_get_stack_var(); 125 126 m_apm_multiply(tmp1, xx, xx); 127 m_apm_round(t2, (places + 4), tmp1); /* x ^ 2 */ 128 129 m_apm_multiply(tmp1, t2, xx); 130 m_apm_round(t3, (places + 4), tmp1); /* x ^ 3 */ 131 132 m_apm_multiply(t5, t2, t3); /* x ^ 5 */ 133 134 m_apm_multiply(tmp0, xx, MM_Five); 135 m_apm_multiply(tmp1, t5, MM_5x_Sixteen); 136 m_apm_add(t2, tmp0, tmp1); 137 m_apm_multiply(tmp1, t3, MM_5x_Twenty); 138 m_apm_subtract(tmp0, t2, tmp1); 139 140 m_apm_round(rr, places, tmp0); 141 M_restore_stack(5); 142 } 143 /****************************************************************************/ 144 /* 145 * calculate the multiple angle identity for cos (4x) 146 * 147 * cos (4x) == 8 * [ cos^4 (x) - cos^2 (x) ] + 1 148 */ 149 void M_4x_do_it(M_APM rr, int places, M_APM xx) 150 { 151 M_APM tmp0, tmp1, t2, t4; 152 153 tmp0 = M_get_stack_var(); 154 tmp1 = M_get_stack_var(); 155 t2 = M_get_stack_var(); 156 t4 = M_get_stack_var(); 157 158 m_apm_multiply(tmp1, xx, xx); 159 m_apm_round(t2, (places + 4), tmp1); /* x ^ 2 */ 160 m_apm_multiply(t4, t2, t2); /* x ^ 4 */ 161 162 m_apm_subtract(tmp0, t4, t2); 163 m_apm_multiply(tmp1, tmp0, MM_5x_Eight); 164 m_apm_add(tmp0, MM_One, tmp1); 165 m_apm_round(rr, places, tmp0); 166 M_restore_stack(4); 167 } 168 /****************************************************************************/ 169 /* 170 * compute r = sqrt(1 - a ^ 2). 171 */ 172 void M_cos_to_sin(M_APM r, int places, M_APM a) 173 { 174 M_APM tmp1, tmp2; 175 176 tmp1 = M_get_stack_var(); 177 tmp2 = M_get_stack_var(); 178 179 m_apm_multiply(tmp1, a, a); 180 m_apm_subtract(tmp2, MM_One, tmp1); 181 m_apm_sqrt(r, places, tmp2); 182 M_restore_stack(2); 183 } 184 /****************************************************************************/ 185