OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [Float128.cpp] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
 
2
#include "stdafx.h"
3
 
4
Float128::Float128(Float128 *a)
5
{
6
        int nn;
7
 
8
        for (nn = 0; nn < FLT128_WORDS; nn++)
9
                man[nn] = a->man[nn];
10
        exp = a->exp;
11
        sign = a->sign;
12
}
13
 
14
// Check if mantissas are equal
15
 
16
bool Float128::ManEQ(Float128 *a, Float128 *b)
17
{
18
        int nn;
19
 
20
        for (nn = FLT128_WORDS-1; nn >= 0; nn--) {
21
                if (a->man[nn]!=b->man[nn])
22
                        return (false);
23
        }
24
        return (true);
25
}
26
 
27
bool Float128::ManGT(Float128 *a, Float128 *b)
28
{
29
        int nn;
30
 
31
        for (nn = FLT128_WORDS-1; nn >= 0; nn--) {
32
                if (a->man[nn] > b->man[nn])
33
                        return (true);
34
                else if (a->man[nn] < b->man[nn])
35
                        return (false);
36
        }
37
        return (false);
38
}
39
 
40
// Does nothing but shift mantissa left. Zeros are shited in at the low end.
41
 
42
void Float128::ShiftManLeft()
43
{
44
        int nn;
45
        unsigned __int32 c[FLT128_WORDS];
46
 
47
        for (nn = 0; nn < FLT128_WORDS; nn++) {
48
                c[nn] = (man[nn] >> 31) & 1;
49
        }
50
        man[0] <<= 1;
51
        for (nn = 1; nn < FLT128_WORDS; nn++) {
52
                man[nn] <<= 1;
53
                man[nn] |= c[nn-1];
54
        }
55
}
56
 
57
// Does nothing but shift mantissa right.
58
 
59
void Float128::ShiftManRight()
60
{
61
        int nn;
62
        unsigned __int32 c[FLT128_WORDS];
63
 
64
        for (nn = 0; nn < FLT128_WORDS; nn++) {
65
                c[nn] = (man[nn] & 1) << 31;
66
        }
67
        man[FLT128_WORDS-1] >>= 1;
68
        for (nn = FLT128_WORDS-2; nn >= 0; nn--) {
69
                man[nn] >>= 1;
70
                man[nn] |= c[nn+1];
71
        }
72
}
73
 
74
void Float128::Normalize(Float128 *a)
75
{
76
        int nn;
77
 
78
        for(nn = 0; nn < FLT128_WORDS*32-1; nn++) {
79
                if (a->man[FLT128_WORDS-1] & 0xC0000000)
80
                        break;
81
                if (a->exp==0)   // Denormal
82
                        break;
83
                a->ShiftManLeft();
84
                a->exp = a->exp - 1;
85
        }
86
}
87
 
88
// Denormalization used for addition / subtraction.
89
 
90
void Float128::Denormalize(unsigned __int16 xp)
91
{
92
        if (exp >= xp)
93
                return;
94
        if (xp - exp > FLT128_WORDS*32-1) {
95
                exp = xp;
96
                Zeroman();
97
                return;
98
        }
99
        while(exp < xp) {
100
                ShiftManRight();
101
                exp++;
102
        }
103
}
104
 
105
// Used after an addition in event of a new bit generated.
106
void Float128::Denorm1()
107
{
108
        ShiftManRight();
109
        man[FLT128_WORDS-1] |= 0x40000000;
110
        exp++;
111
        // Check for infinity
112
        if (exp & 0x8000) {
113
                exp = infxp;
114
                Zeroman();
115
        }
116
}
117
 
118
// Does nothing but add the mantissas.
119
// Return true if a new bit was generated.
120
 
121
bool Float128::AddMan(Float128 *s, Float128 *a, Float128 *b)
122
{
123
        int nn;
124
        unsigned __int64 sum[FLT128_WORDS];
125
        unsigned __int64 c;
126
 
127
        c = 0;
128
        for (nn = 0; nn < FLT128_WORDS; nn++) {
129
                sum[nn] = (unsigned __int64)a->man[nn] + (unsigned __int64)b->man[nn] + c;
130
                c = (sum[nn] >> 32) & 1;
131
        }
132
        for (nn = 0; nn < FLT128_WORDS; nn++) {
133
                s->man[nn] = (unsigned __int32)sum[nn];
134
        }
135
        return ((sum[FLT128_WORDS-1] & 0x80000000)!=0);
136
}
137
 
138
// Does nothing but subtract the mantissas.
139
 
140
bool Float128::SubMan(Float128 *d, Float128 *a, Float128 *b)
141
{
142
        int nn;
143
        unsigned __int64 sum[FLT128_WORDS];
144
        unsigned __int64 c;
145
 
146
        c = 0;
147
        for (nn = 0; nn < FLT128_WORDS; nn++) {
148
                sum[nn] = (unsigned __int64)a->man[nn] - (unsigned __int64)b->man[nn] - c;
149
                c = (sum[nn] >> 32) & 1;
150
        }
151
        for (nn = 0; nn < FLT128_WORDS; nn++) {
152
                d->man[nn] = (unsigned __int32)sum[nn];
153
        }
154
        return ((sum[FLT128_WORDS-1] & 0x80000000)!=0);
155
}
156
 
157
 
158
// Add also used for subtract
159
 
160
void Float128::Add(Float128 *s, Float128 *a, Float128 *b)
161
{
162
        Float128 *a1 = new Float128(a);
163
        Float128 *b1 = new Float128(b);
164
        bool addsub = a1->sign ^ b1->sign;      // 0 = add, 1=subtract
165
        bool xa_gt_xb = a1->exp > b1->exp;
166
        bool a_gt_b = xa_gt_xb || ManGT(a1,b1);
167
        bool resZero = addsub && a->exp==b->exp && ManEQ(a,b);
168
 
169
        if (a->IsNaN()) {
170
                Assign(s,a);
171
                return;
172
        }
173
        if (b->IsNaN()) {
174
                Assign(s,b);
175
                return;
176
        }
177
 
178
        if (resZero) {
179
                s->exp = 0;
180
                s->Zeroman();
181
                return;
182
        }
183
 
184
        // Infinity minus infinity is a NaN
185
        if (addsub) {
186
                if (a->IsInfinite() && b->IsInfinite()) {
187
                        s->exp = infxp;
188
                        s->Zeroman();
189
                        s->man[FLT128_WORDS-1] = 0x40000000;    // Querying NaN
190
                        s->man[FLT128_WORDS/2-1] = 0x80000000;  // Code 1
191
                        return;
192
                }
193
        }
194
        // Infinity plus infinity is infinity
195
        else if (a->IsInfinite() && b->IsInfinite()) {
196
                s->sign = a->sign;
197
                s->exp = infxp;
198
                s->Zeroman();
199
                return;
200
        }
201
 
202
        a1 = new Float128(a);
203
        b1 = new Float128(b);
204
        if (a1->exp > b1->exp)
205
                b1->Denormalize(a1->exp);
206
        else if (a1->exp < b1->exp)
207
                a1->Denormalize(b1->exp);
208
 
209
        // Exponents are now the same
210
        // If the signs are different we really want a subtract
211
        if (addsub) {
212
                if (a_gt_b) {
213
                        SubMan(s, a1,b1);
214
                        s->exp = a1->exp;
215
                }
216
                else {
217
                        SubMan(s, b1,a1);
218
                        s->exp = b1->exp;
219
                }
220
                Normalize(s);
221
        }
222
        else {
223
                s->exp = a1->exp;
224
                if (AddMan(s,a1,b1))
225
                        s->Denorm1();
226
        }
227
        delete a1;
228
        delete b1;
229
}
230
 
231
void Float128::Div(Float128 *q, Float128 *a, Float128 *b)
232
{
233
        int nn;
234
        Float128 *a1;
235
        Float128 *b1;
236
        int a_dn, b_dn;
237
        a_dn = a->exp==0;
238
        b_dn = b->exp==0;
239
        __int32 xp = (a->exp|a_dn) - (b->exp|b_dn) + bias;
240
        q->sign = a->sign ^ b->sign;
241
 
242
        if (a->IsNaN()) {
243
                Assign(q,a);
244
                return;
245
        }
246
        if (b->IsNaN()) {
247
                Assign(q,b);
248
                return;
249
        }
250
 
251
        // Check for zero divide by zero
252
        // or infinity divide by infinity
253
        if ((a->IsZero() && b->IsZero()) || (a->IsInfinite() && b->IsInfinite())) {
254
                q->exp = infxp;
255
                q->Zeroman();
256
                q->man[FLT128_WORDS-1] = 0x40000000;    // Querying NaN
257
                q->man[FLT128_WORDS/2] = a->IsZero();
258
                q->man[FLT128_WORDS/2-1] = b->IsZero() << 31;
259
                return;
260
        }
261
 
262
        // Divide by infinity
263
        if (b->IsInfinite()) {
264
                q->exp = 0;
265
                q->Zeroman();
266
                return;
267
        }
268
 
269
        // Divide by zero ?
270
        if (b->IsZero()) {
271
                q->exp = infxp;
272
                q->Zeroman();
273
                return;
274
        }
275
 
276
        if (a->IsZero()) {
277
                q->Zeroman();
278
                q->exp = 0;
279
                return;
280
        }
281
 
282
        a1 = new Float128(a);
283
        b1 = new Float128(b);
284
        q->Zeroman();
285
        for (nn = 0; nn < FLT128_WORDS*32-1; nn++) {
286
                q->ShiftManLeft();
287
                if (ManGE(a1,b)) {
288
                        SubMan(a1,a1,b);
289
                        q->man[0] |= 1;
290
                }
291
                a1->ShiftManLeft();
292
        }
293
        q->exp = xp;
294
        Normalize(q);
295
        delete a1;
296
        delete b1;
297
}
298
 
299
 
300
void Float128::Mul(Float128 *p, Float128 *a, Float128 *b)
301
{
302
        int nn;
303
        Float128 *a1;
304
        Float128 *b1;
305
        int a_dn, b_dn;
306
        a_dn = a->exp==0;
307
        b_dn = b->exp==0;
308
        __int32 xp = (a->exp|a_dn) + (b->exp|b_dn) - bias + 1;
309
 
310
        p->sign = a->sign ^ b->sign;
311
 
312
        if (a->IsNaN()) {
313
                Assign(p,a);
314
                return;
315
        }
316
        if (b->IsNaN()) {
317
                Assign(p,b);
318
                return;
319
        }
320
 
321
        // Check for infinity times zero.
322
        if ((a->IsZero() && b->IsInfinite()) || (a->IsInfinite() && b->IsZero())) {
323
                p->exp = infxp;
324
                p->Zeroman();
325
                p->man[FLT128_WORDS-1] = 0x40000000;    // Querying NaN
326
                p->man[FLT128_WORDS/2] = 0x00000002;
327
                return;
328
        }
329
 
330
        // Check for multiply by zero
331
        if (a->IsZero() || b->IsZero()) {
332
                p->Zeroman();
333
                p->exp = 0;
334
                return;
335
        }
336
 
337
        // Check for multiply by infinity
338
        if (a->IsInfinite() || b->IsInfinite()) {
339
                p->exp = infxp;
340
                p->Zeroman();
341
                return;
342
        }
343
 
344
        // Infinity reached ?
345
        if (xp & 0x8000) {
346
                p->exp = infxp;
347
                p->Zeroman();
348
                return;
349
        }
350
 
351
        a1 = new Float128(a);
352
        b1 = new Float128(b);
353
        p->Zeroman();
354
        for (nn = 0; nn < FLT128_WORDS*32/2; nn++)
355
                b1->ShiftManRight();
356
        for (nn = 0; nn < FLT128_WORDS*32/2; nn++) {
357
                if (a1->man[FLT128_WORDS/2-1] & 0x80000000) {
358
                        if (AddMan(p,p,b1))             // Can't generate a new bit
359
                                printf("bit gen");      // during multiply
360
                }
361
                a1->ShiftManRight();
362
                b1->ShiftManLeft();
363
        }
364
        p->exp = xp;
365
        Normalize(p);
366
        delete a1;
367
        delete b1;
368
}
369
 
370
void Float128::IntToFloat(Float128 *d, __int64 i)
371
{
372
        unsigned __int16 wd;
373
        unsigned __int16 lz;
374
        bool sign = i < 0;
375
 
376
        d->Zeroman();
377
        if (i==0) {
378
                d->exp = 0;
379
                d->sign = false;
380
                return;
381
        }
382
        if (sign)
383
                i = -i;
384
        for (lz = 0; (i & 0x8000000000000000LL)==0; lz++)
385
                i <<= 1;
386
        wd = 128 + bias - 1 - lz - 64;
387
        d->exp = wd;
388
        d->sign = sign;
389
        d->man[FLT128_WORDS-1] = (unsigned __int64) i >> 33;
390
        d->man[FLT128_WORDS-2] = ((i >> 1) & 0xFFFFFFFFLL);
391
        d->man[FLT128_WORDS-3] = ((i & 1) << 31);
392
}
393
 
394
void Float128::FloatToInt(__int64 *i, Float128 *a)
395
{
396
        Float128 *a1 = new Float128(a);
397
        bool overflow = a1->exp - bias > 63;
398
        bool underflow = a1->exp < bias - 1;
399
        int shamt = 63 - (a1->exp - bias);
400
        unsigned __int64 t;
401
 
402
        if (overflow) {
403
                a1->man[FLT128_WORDS-1] = 0x3FFFFFFF;
404
                a1->man[FLT128_WORDS-2] = 0xFFFFFFFF;
405
                a1->man[FLT128_WORDS-3] = 0xFFFFFFFF;
406
        }
407
        else if (underflow) {
408
                a1->Zeroman();
409
        }
410
        else if (shamt > FLT128_WORDS*32-1) {
411
                a1->Zeroman();
412
        }
413
        else if (shamt < 0) {
414
        }
415
        else {
416
                while(shamt) {
417
                        a1->ShiftManRight();
418
                        shamt--;
419
                }
420
        }
421
        if (a1->man[FLT128_WORDS-4] & 0x08000) {
422
                t = a1->man[FLT128_WORDS-4];
423
                t += 0x10000;
424
                if (t & 0x100000000) {
425
                        a1->man[FLT128_WORDS-3]++;
426
                        if (a1->man[FLT128_WORDS-3]==0) {
427
                                a1->man[FLT128_WORDS-2]++;
428
                                if (a1->man[FLT128_WORDS-2]==0) {
429
                                        a1->man[FLT128_WORDS-1]++;
430
                                        if (a1->man[FLT128_WORDS-1] & 0x80000000) {
431
                                                a1->ShiftManRight();
432
                                                a1->exp++;
433
                                                if (a1->exp & 0x8000) {
434
                                                        a1->exp = 0x7fff;
435
                                                        a1->Zeroman();
436
                                                }
437
                                        }
438
                                }
439
                        }
440
                }
441
        }
442
        t = (a1->man[FLT128_WORDS-1] << 1) | (a1->man[FLT128_WORDS-2] << 1) | (a1->man[FLT128_WORDS-3] >> 31);
443
        *i = a1->sign ? -t : t;
444
        delete (a1);
445
}
446
 
447
void Float128::Float128ToDouble(double *d, Float128 *a)
448
{
449
        bool sgn;
450
        unsigned __int16 exp;
451
        __int64 *di = (__int64 *)d;
452
 
453
        // Do we have a zero ?
454
        if (a->IsZero()) {
455
                *di = a->sign ? 0x8000000000000000LL : 0x0000000000000000LL;
456
                return;
457
        }
458
        // Or an infinite number ?
459
        if (a->IsInfinite()) {
460
                *di = a->sign ? 0xFFF0000000000000LL : 0x7FF0000000000000LL;
461
                return;
462
        }
463
        // Too large a number -> infinity
464
        if (a->exp > a->bias + 0x400) {
465
                *di = a->sign ? 0xFFF0000000000000LL : 0x7FF0000000000000LL;
466
                return;
467
        }
468
        // Too small a number -> zero
469
        if (a->exp < a->bias - 0x3ff) {
470
                *di = a->sign ? 0x8000000000000000LL : 0x0000000000000000LL;
471
        }
472
        sgn = a->sign;
473
        exp = a->exp - (bias - 0x3ff);
474
        *di = (__int64)sgn << 63;
475
        *di |= (__int64)exp << 52;
476
        *di |= (__int64)(a->man[FLT128_WORDS-1] & 0x3FFFFFFFL) << 22;
477
        *di |= (__int64)a->man[FLT128_WORDS-2] >> 10;
478
}
479
 
480
void Float128::Pack(int prec)
481
{
482
        Float128 a;
483
        if (man[FLT128_WORDS-5] & 0x40000000) {
484
                man[FLT128_WORDS-5] += 0x80000000;
485
                if ((man[FLT128_WORDS-5] & 0x80000000)==0) {
486
                        man[FLT128_WORDS-4]++;
487
                        if (man[FLT128_WORDS-4]==0) {
488
                                man[FLT128_WORDS-3]++;
489
                                if (man[FLT128_WORDS-3]==0) {
490
                                        man[FLT128_WORDS-2]++;
491
                                        if (man[FLT128_WORDS-2]==0) {
492
                                                man[FLT128_WORDS-1]++;
493
                                                if (man[FLT128_WORDS-1] & 0x80000000) {
494
                                                        exp++;
495
                                                        ShiftManRight();
496
                                                        if (exp & 0x8000) {
497
                                                                exp = 0x7FFF;
498
                                                                man[FLT128_WORDS-1] = 0;
499
                                                        }
500
                                                }
501
                                        }
502
                                }
503
                        }
504
                }
505
        }
506
        Float128::Assign(&a,this);
507
        a.ShiftManLeft();
508
        a.ShiftManLeft();
509
        if (prec==64) {
510
                double d;
511
                __int32 *p = (__int32 *)&d;
512
                Float128ToDouble(&d,this);
513
                pack[3] = p[1];
514
                pack[2] = p[0];
515
        }
516
        else if (prec==80) {
517
                pack[3] = (((unsigned __int32)sign << 31) | (unsigned __int32)exp << 16) | (a.man[FLT128_WORDS-1] >> 16);
518
                pack[2] = ((a.man[FLT128_WORDS-1] & 0xFFFF) << 16) | (a.man[FLT128_WORDS-2] >> 16);
519
                pack[1] = ((a.man[FLT128_WORDS-2] & 0xFFFF) << 16) | (a.man[FLT128_WORDS-3] >> 16);
520
        }
521
        else {
522
                pack[3] = (((unsigned __int32)sign << 31) | (unsigned __int32)exp << 16) | (a.man[FLT128_WORDS-1] >> 16);
523
                pack[2] = ((a.man[FLT128_WORDS-1] & 0xFFFF) << 16) | (a.man[FLT128_WORDS-2] >> 16);
524
                pack[1] = ((a.man[FLT128_WORDS-2] & 0xFFFF) << 16) | (a.man[FLT128_WORDS-3] >> 16);
525
                pack[0] = ((a.man[FLT128_WORDS-3] & 0xFFFF) << 16) | (a.man[FLT128_WORDS-4] >> 16);
526
        }
527
}
528
 
529
char *Float128::ToString()
530
{
531
        static char buf[50];
532
 
533
        Pack(FLT_PREC);
534
        switch(FLT_PREC) {
535
        case 64:
536
                sprintf_s(buf,sizeof(buf),"0x%08X,0x%08X", pack[2],pack[3]);
537
                break;
538
        case 80:
539
                sprintf_s(buf,sizeof(buf),"0x%08X,0x%08X,0x%08X", pack[1],pack[2],pack[3]);
540
                break;
541
        case 128:
542
                sprintf_s(buf,sizeof(buf),"0x%08X,0x%08X,0x%08X,0x%08X", pack[0],pack[1],pack[2],pack[3]);
543
                break;
544
        }
545
        return (buf);
546
}
547
 
548
char *Float128::ToString(int prec)
549
{
550
        static char buf[50];
551
 
552
        Pack(prec);
553
        switch(prec) {
554
        case 64:
555
                sprintf_s(buf,sizeof(buf),"0x%08X,0x%08X", pack[2],pack[3]);
556
                break;
557
        case 80:
558
                sprintf_s(buf,sizeof(buf),"0x%08X,0x%08X,0x%08X", pack[1],pack[2],pack[3]);
559
                break;
560
        case 128:
561
                sprintf_s(buf,sizeof(buf),"0x%08X,0x%08X,0x%08X,0x%08X", pack[0],pack[1],pack[2],pack[3]);
562
                break;
563
        }
564
        return (buf);
565
}
566
 
567
bool Float128::IsManZero() const
568
{
569
        int nn;
570
 
571
        for (nn = 0; nn < FLT128_WORDS; nn++) {
572
                if (man[nn] != 0)
573
                        return (false);
574
        }
575
        return (true);
576
}
577
 
578
 
579
// Zero could be either + or -.
580
bool Float128::IsZero() const
581
{
582
        if (exp != 0)
583
                return (false);
584
        return (IsManZero());
585
}
586
 
587
bool Float128::IsEqual(Float128 *a, Float128 *b)
588
{
589
        if (a->IsZero() && b->IsZero())
590
                return (true);
591
        if (a->sign != b->sign)
592
                return (false);
593
        if (a->exp != b->exp)
594
                return (false);
595
        if (!ManEQ(a,b))
596
                return (false);
597
        return (true);
598
}
599
 
600
// IsEqual test without zero checking.
601
 
602
bool Float128::IsEqualNZ(Float128 *a, Float128 *b)
603
{
604
        if (a->sign != b->sign)
605
                return (false);
606
        if (a->exp != b->exp)
607
                return (false);
608
        if (!ManEQ(a,b))
609
                return (false);
610
        return (true);
611
}
612
 
613
bool Float128::IsNaN(Float128 *a)
614
{
615
        if (a->exp==infxp && !a->IsManZero())
616
                return (true);
617
        return (false);
618
}
619
 
620
bool Float128::IsInfinite() const
621
{
622
        return (exp==infxp && IsManZero());
623
}
624
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.