summaryrefslogtreecommitdiff
path: root/mpu/st-exp.c
blob: aa18d0fac3ae8507eb5b1ca8ac69996edb57894e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
/***************************************************************
  __ST_EXP.C

       This file contains source code of functions for
       EXP constants operations.

       PART OF : MPU - library .

       USAGE   : Internal only .

       NOTE    : NONE .

       Copyright (C) 2000 - 2024  by Andrew V.Kosteltsev.
       All Rights Reserved.
 ***************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <errno.h>   /* errno(3)  */
#include <string.h>  /* strcpy(3) */
#include <strings.h> /* bzero(3)  */
#include <stdlib.h>

#include <libmpu.h>
#include <mpu-context.h>

#include <mpu-emutype.h>
#include <mpu-integer.h>
#include <mpu-real.h>
#include <mpu-floatp.h>

#include <mpu-char.h>
#include <mpu-symbols.h>

#include <mpu-math-errno.h>
#include <mpu-mtherr.h>


/***************************************************************
  Кодировка имен файлов:

  Трехзначное десятичное число, представляющее количество
  128-и битных слов, из которых состоят вещественные числа
  размещенные в массивах:

    размер чисел в битах  кодировка
    --------------------  ---------
                     128  001
                     256  002
                     512  004
                    1024  008
                    2048  016
                    4096  032
                    8192  064
                   16384  128
                   32768  256
                   65536  512 (это предел);

    ПРИМЕРЫ:
    -------
      ei_exp_001_emu32lsb.dfn -   128-бит,
      ei_exp_512_emu32lsb.dfn - 65536-бит.

 ***************************************************************/

#if MPU_MATH_FN_LIMIT >= 128
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu00128/ei_exp_001_emu32lsb.dfn>
#else
#include <math/exp/emu00128/ei_exp_001_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 128 */

#if MPU_MATH_FN_LIMIT >= 256
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu00256/ei_exp_002_emu32lsb.dfn>
#else
#include <math/exp/emu00256/ei_exp_002_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 256 */

#if MPU_MATH_FN_LIMIT >= 512
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu00512/ei_exp_004_emu32lsb.dfn>
#else
#include <math/exp/emu00512/ei_exp_004_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 512 */

#if MPU_MATH_FN_LIMIT >= 1024
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu01024/ei_exp_008_emu32lsb.dfn>
#else
#include <math/exp/emu01024/ei_exp_008_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 1024 */

#if MPU_MATH_FN_LIMIT >= 2048
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu02048/ei_exp_016_emu32lsb.dfn>
#else
#include <math/exp/emu02048/ei_exp_016_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 2048 */

#if MPU_MATH_FN_LIMIT >= 4096
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu04096/ei_exp_032_emu32lsb.dfn>
#else
#include <math/exp/emu04096/ei_exp_032_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 4096 */

#if MPU_MATH_FN_LIMIT >= 8192
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu08192/ei_exp_064_emu32lsb.dfn>
#else
#include <math/exp/emu08192/ei_exp_064_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 8192 */

#if MPU_MATH_FN_LIMIT >= 16384
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu16384/ei_exp_128_emu32lsb.dfn>
#else
#include <math/exp/emu16384/ei_exp_128_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 16384 */

#if MPU_MATH_FN_LIMIT >= 32768
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu32768/ei_exp_256_emu32lsb.dfn>
#else
#include <math/exp/emu32768/ei_exp_256_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 32768 */

#if MPU_MATH_FN_LIMIT >= 65536
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <math/exp/emu65536/ei_exp_512_emu32lsb.dfn>
#else
#include <math/exp/emu65536/ei_exp_512_emu32msb.dfn>
#endif
#endif /* MPU_MATH_FN_LIMIT >= 65536 */


static int _get_n_exp( int nb )
{
  int  rc = 0;

  if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
  {
    /* error: Invalid size of operand(s) */
    __real_error_no = __R_ESIZE__;
    __STIND; /* Set REAL ind-produsing operation Flag */
    return( rc );
  }

  switch( nb )
  {
#if MPU_MATH_FN_LIMIT >= 128
    case NBR_32   :
    case NBR_64   :
    case NBR_128  :
      rc = N_EXP_E128;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 128 */
#if MPU_MATH_FN_LIMIT >= 256
    case NBR_256  :
      rc = N_EXP_E256;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 256 */
#if MPU_MATH_FN_LIMIT >= 512
    case NBR_512  :
      rc = N_EXP_E512;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 512 */
#if MPU_MATH_FN_LIMIT >= 1024
    case NBR_1024 :
      rc = N_EXP_E1024;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 1024 */
#if MPU_MATH_FN_LIMIT >= 2048
    case NBR_2048 :
      rc = N_EXP_E2048;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 2048 */
#if MPU_MATH_FN_LIMIT >= 4096
    case NBR_4096 :
      rc = N_EXP_E4096;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 4096 */
#if MPU_MATH_FN_LIMIT >= 8192
    case NBR_8192 :
      rc = N_EXP_E8192;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 8192 */
#if MPU_MATH_FN_LIMIT >= 16384
    case NBR_16384:
      rc = N_EXP_E16384;
      break;
#endif /* MPU_MATH_FN_LIMIT >= 16384 */

    default:
    {
      /* error: Invalid size of operand(s) */
      __real_error_no = __R_ESIZE__;
      __STIND; /* Set REAL ind-produsing operation Flag */
      break;
    }

  } /* End of switch( nb ) */

  return( rc );

} /* End of _get_n_exp() */


static EMUSHORT *_get_exp__E_ptr( int nb )
{
  EMUSHORT *rc = (EMUSHORT *)NULL;

  if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
  {
    /* error: Invalid size of operand(s) */
    __real_error_no = __R_ESIZE__;
    __STIND; /* Set REAL ind-produsing operation Flag */
    return( rc );
  }

  switch( nb )
  {
#if MPU_MATH_FN_LIMIT >= 128
    case NBR_32   :
    case NBR_64   :
    case NBR_128  :
      rc = (EMUSHORT *)&_ei_exp__E_128_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 128 */
#if MPU_MATH_FN_LIMIT >= 256
    case NBR_256  :
      rc = (EMUSHORT *)&_ei_exp__E_256_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 256 */
#if MPU_MATH_FN_LIMIT >= 512
    case NBR_512  :
      rc = (EMUSHORT *)&_ei_exp__E_512_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 512 */
#if MPU_MATH_FN_LIMIT >= 1024
    case NBR_1024 :
      rc = (EMUSHORT *)&_ei_exp__E_1024_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 1024 */
#if MPU_MATH_FN_LIMIT >= 2048
    case NBR_2048 :
      rc = (EMUSHORT *)&_ei_exp__E_2048_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 2048 */
#if MPU_MATH_FN_LIMIT >= 4096
    case NBR_4096 :
      rc = (EMUSHORT *)&_ei_exp__E_4096_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 4096 */
#if MPU_MATH_FN_LIMIT >= 8192
    case NBR_8192 :
      rc = (EMUSHORT *)&_ei_exp__E_8192_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 8192 */
#if MPU_MATH_FN_LIMIT >= 16384
    case NBR_16384:
      rc = (EMUSHORT *)&_ei_exp__E_16384_[0][0];
      break;
#endif /* MPU_MATH_FN_LIMIT >= 16384 */

    default:
    {
      /* error: Invalid size of operand(s) */
      __real_error_no = __R_ESIZE__;
      __STIND; /* Set REAL ind-produsing operation Flag */
      break;
    }

  } /* End of switch( nb ) */

  return( rc );

} /* End of _get_exp__E_ptr() */


void ei_exp__E( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************

 Description        : ei_exp__E() Работает с
                                  internal e-type data struct.

 Concepts           : SEE: ei_exp() [polinom R].

 ACCURACY           : In the absence of rounding error,
                      the appriximation has absolute error
                      less than EPSILON [see: FLOATP.H].

 NOTE               : The coefficient L's are obtained by
                      a special Remez algorithm.

            ===============================================
            В INTERNET я нашел следующие алгоритмы:

            409  cacm  355  356 14  5  May 1971 e2 A60
            ------------------------------------------
               H. Schmitt;
                  Discrete {Chebychev} Curve Fit
                  approximation;Chebyshev approximation;
                  Chebyshev curve fitting;
                 +Chebyshev polynomial;
                  curve approximation;curve fitting;
                  exchange algorithm;
                 +polynomial approximation;Remez algorithm;

            501  toms   95   97  2  1  March 1976 e2 F K2
            ---------------------------------------------
               J. C. Simpson;
                  {FORTRAN} Translation of Algorithm 409
                  Discrete {Chebyshev} Curve Fit
                  approximation;polynomial approximation;
                  exchange algorithm;
                 +Chebyshev approximation;
                  polynomial approximation;
                  R,toms,95,4,1,March,1978,F. Futrell;

            последний из которых я перевел на "С", затем
            на язык операций повышенной разрядности.

            ===============================================
 
 Use Global Variable:

 Use Functions      : internal_np( nb );          | real.c
                      ei_copy( eiy, eix, nb );    | real.c
                      _gen_zero( eic, nb );       | real.c
                      ei_add( eic,eia,eib,nb );   | real.c
                      ei_mul( eic,eia,eib,nb );   | real.c

 Parameters         : EMUSHORT *eiy; - указатель на
                                       internal e-type
                                       data struct.
                                       TARGET;
                      EMUSHORT *eix; - указатель на
                                       internal e-type
                                       data struct.
                                       SOURCE;
                      int nb;        - количество бит в
                                       external e-type
                                       data struct.

 Return             : [void]

 ***************************************************************/
{
   EMUSHORT *x = NULL, *y = NULL;
   EMUSHORT *p;
   int       np;
   int       i, n = _get_n_exp( nb );

   np = internal_np( nb );

   /*** Allocate memory for x, y . *****************************/
   x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
   if( !x )
   {
     /* fatal error */
     return;
   }

   y = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
   if( !y )
   {
     /* fatal error */

     /* FREE x *****************/
     __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
     /**************************/

     return;
   }
   /************************************************************/

   _gen_zero( y, nb );
   ei_copy( x, eix, nb );
   p = _get_exp__E_ptr( nb );
   for( i = 0; i < n; i++ )
   {
     ei_add( y, y, p, nb );
     ei_mul( y, y, x, nb );
     p += np;
   }

   ei_copy( eiy, y, nb );

   /* FREE x *****************/
   /* FREE y *****************/
   __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
   /**************************/

} /* End of ei_exp__E() */


/***************************************************************
  Hide internal symbols:
 ***************************************************************/

__mpu_hidden_decl(ei_exp__E);


/*
  End of hide internal symbols.
 ***************************************************************/