float.cpp 18.4 KB
Newer Older
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1
// Copyright (c) 2014 Dropbox, Inc.
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3 4 5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
Kevin Modzelewski's avatar
Kevin Modzelewski committed
6
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
7
//    http://www.apache.org/licenses/LICENSE-2.0
Kevin Modzelewski's avatar
Kevin Modzelewski committed
8
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
9 10 11 12 13 14 15 16 17
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cmath>
#include <cstring>

18
#include "codegen/compvars.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
19 20
#include "core/types.h"
#include "runtime/gc_runtime.h"
21
#include "runtime/inline/boxing.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
22 23 24 25 26 27
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"

namespace pyston {

28
template <typename T> static inline void raiseDivZeroExcIfZero(T var) {
29
    if (var == 0) {
30
        raiseExcHelper(ZeroDivisionError, "float divide by zero");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
31
    }
32 33 34 35
}

extern "C" double mod_float_float(double lhs, double rhs) {
    raiseDivZeroExcIfZero(rhs);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    double r = fmod(lhs, rhs);
    // Have to be careful here with signed zeroes:
    if (std::signbit(r) != std::signbit(rhs)) {
        if (r == 0)
            r *= -1;
        else
            r += rhs;
    }
    return r;
}

extern "C" double pow_float_float(double lhs, double rhs) {
    return pow(lhs, rhs);
}

extern "C" double div_float_float(double lhs, double rhs) {
52
    raiseDivZeroExcIfZero(rhs);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
53 54 55
    return lhs / rhs;
}

56
extern "C" Box* floatAddFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
57 58
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
59 60 61
    return boxFloat(lhs->d + rhs->d);
}

62
extern "C" Box* floatAddInt(BoxedFloat* lhs, BoxedInt* rhs) {
63 64 65
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxFloat(lhs->d + rhs->n);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
66 67
}

68
extern "C" Box* floatAdd(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
69 70
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
71
        return floatAddInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
72
    } else if (rhs->cls == float_cls) {
73
        return floatAddFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
74 75 76 77 78
    } else {
        return NotImplemented;
    }
}

79
extern "C" Box* floatDivFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
80 81 82 83 84 85
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    raiseDivZeroExcIfZero(rhs->d);
    return boxFloat(lhs->d / rhs->d);
}

86
extern "C" Box* floatDivInt(BoxedFloat* lhs, BoxedInt* rhs) {
87 88 89 90 91 92
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    raiseDivZeroExcIfZero(rhs->n);
    return boxFloat(lhs->d / rhs->n);
}

93
extern "C" Box* floatDiv(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
94 95
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
96
        return floatDivInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
97
    } else if (rhs->cls == float_cls) {
98
        return floatDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
99 100 101 102 103
    } else {
        return NotImplemented;
    }
}

104
extern "C" Box* floatRDivFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
105
    assert(lhs->cls == float_cls);
106 107 108 109
    assert(rhs->cls == float_cls);
    raiseDivZeroExcIfZero(lhs->d);
    return boxFloat(rhs->d / lhs->d);
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
110

111
extern "C" Box* floatRDivInt(BoxedFloat* lhs, BoxedInt* rhs) {
112 113 114 115
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    raiseDivZeroExcIfZero(lhs->d);
    return boxFloat(rhs->n / lhs->d);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
116 117
}

118
extern "C" Box* floatRDiv(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
119
    assert(lhs->cls == float_cls);
120 121 122 123
    if (rhs->cls == int_cls) {
        return floatRDivInt(lhs, static_cast<BoxedInt*>(rhs));
    } else if (rhs->cls == float_cls) {
        return floatRDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
124 125 126 127 128
    } else {
        return NotImplemented;
    }
}

129
extern "C" Box* floatFloorDiv(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
130 131 132 133
    assert(lhs->cls == float_cls);
    if (rhs->cls != float_cls) {
        return NotImplemented;
    }
134
    BoxedFloat* rhs_float = static_cast<BoxedFloat*>(rhs);
135
    raiseDivZeroExcIfZero(rhs_float->d);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
136 137 138
    return boxFloat(floor(lhs->d / rhs_float->d));
}

139
extern "C" Box* floatEqFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
140 141 142 143 144
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxBool(lhs->d == rhs->d);
}

145
extern "C" Box* floatEqInt(BoxedFloat* lhs, BoxedInt* rhs) {
146 147 148 149 150
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxBool(lhs->d == rhs->n);
}

151
extern "C" Box* floatEq(BoxedFloat* lhs, Box* rhs) {
152 153 154 155 156 157 158 159 160 161
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
        return floatEqInt(lhs, static_cast<BoxedInt*>(rhs));
    } else if (rhs->cls == float_cls) {
        return floatEqFloat(lhs, static_cast<BoxedFloat*>(rhs));
    } else {
        return NotImplemented;
    }
}

162
extern "C" Box* floatNeFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
163 164 165 166 167
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxBool(lhs->d != rhs->d);
}

168
extern "C" Box* floatNeInt(BoxedFloat* lhs, BoxedInt* rhs) {
169 170 171 172 173
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxBool(lhs->d != rhs->n);
}

174
extern "C" Box* floatNe(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
175
    assert(lhs->cls == float_cls);
176 177 178 179
    if (rhs->cls == int_cls) {
        return floatNeInt(lhs, static_cast<BoxedInt*>(rhs));
    } else if (rhs->cls == float_cls) {
        return floatNeFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
180 181 182 183 184
    } else {
        return NotImplemented;
    }
}

185
extern "C" Box* floatLtFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
186 187 188 189 190
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxBool(lhs->d < rhs->d);
}

191
extern "C" Box* floatLtInt(BoxedFloat* lhs, BoxedInt* rhs) {
192 193 194 195 196
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxBool(lhs->d < rhs->n);
}

197
extern "C" Box* floatLt(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
198
    assert(lhs->cls == float_cls);
199 200 201 202
    if (rhs->cls == int_cls) {
        return floatLtInt(lhs, static_cast<BoxedInt*>(rhs));
    } else if (rhs->cls == float_cls) {
        return floatLtFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
203 204 205 206 207
    } else {
        return NotImplemented;
    }
}

208
extern "C" Box* floatLeFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
209 210 211 212 213
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxBool(lhs->d <= rhs->d);
}

214
extern "C" Box* floatLeInt(BoxedFloat* lhs, BoxedInt* rhs) {
215 216 217 218 219
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxBool(lhs->d <= rhs->n);
}

220
extern "C" Box* floatLe(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
221
    assert(lhs->cls == float_cls);
222 223 224 225
    if (rhs->cls == int_cls) {
        return floatLeInt(lhs, static_cast<BoxedInt*>(rhs));
    } else if (rhs->cls == float_cls) {
        return floatLeFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
226 227 228 229 230
    } else {
        return NotImplemented;
    }
}

231
extern "C" Box* floatGtFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
232 233 234 235 236
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxBool(lhs->d > rhs->d);
}

237
extern "C" Box* floatGtInt(BoxedFloat* lhs, BoxedInt* rhs) {
238 239 240 241 242
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxBool(lhs->d > rhs->n);
}

243
extern "C" Box* floatGt(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
244
    assert(lhs->cls == float_cls);
245 246 247 248
    if (rhs->cls == int_cls) {
        return floatGtInt(lhs, static_cast<BoxedInt*>(rhs));
    } else if (rhs->cls == float_cls) {
        return floatGtFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
249 250 251 252 253
    } else {
        return NotImplemented;
    }
}

254
extern "C" Box* floatGeFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
255 256 257 258 259
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxBool(lhs->d >= rhs->d);
}

260
extern "C" Box* floatGeInt(BoxedFloat* lhs, BoxedInt* rhs) {
261 262 263 264 265
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxBool(lhs->d >= rhs->n);
}

266
extern "C" Box* floatGe(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
267
    assert(lhs->cls == float_cls);
268 269 270 271
    if (rhs->cls == int_cls) {
        return floatGeInt(lhs, static_cast<BoxedInt*>(rhs));
    } else if (rhs->cls == float_cls) {
        return floatGeFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
272 273 274 275 276
    } else {
        return NotImplemented;
    }
}

277
extern "C" Box* floatModFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
278
    assert(lhs->cls == float_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
279
    assert(rhs->cls == float_cls);
280 281
    return boxFloat(mod_float_float(lhs->d, rhs->d));
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
282

283
extern "C" Box* floatModInt(BoxedFloat* lhs, BoxedInt* rhs) {
284 285 286
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxFloat(mod_float_float(lhs->d, rhs->n));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
287 288
}

289
extern "C" Box* floatMod(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
290 291
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
292
        return floatModInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
293
    } else if (rhs->cls == float_cls) {
294
        return floatModFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
295 296 297 298 299
    } else {
        return NotImplemented;
    }
}

300
extern "C" Box* floatRModFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
301
    assert(lhs->cls == float_cls);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
302
    assert(rhs->cls == float_cls);
303 304
    return boxFloat(mod_float_float(rhs->d, lhs->d));
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
305

306
extern "C" Box* floatRModInt(BoxedFloat* lhs, BoxedInt* rhs) {
307 308 309
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxFloat(mod_float_float(rhs->n, lhs->d));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
310 311
}

312
extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
313 314
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
315
        return floatRModInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
316
    } else if (rhs->cls == float_cls) {
317
        return floatRModFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
318 319 320
    } else {
        return NotImplemented;
    }
321
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
322

323
extern "C" Box* floatPowFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
324 325 326 327
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxFloat(pow(lhs->d, rhs->d));
}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
328

329
extern "C" Box* floatPowInt(BoxedFloat* lhs, BoxedInt* rhs) {
330 331 332
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxFloat(pow(lhs->d, rhs->n));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
333 334
}

335
extern "C" Box* floatPow(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
336 337
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
338
        return floatPowInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
339
    } else if (rhs->cls == float_cls) {
340
        return floatPowFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
341 342 343 344 345
    } else {
        return NotImplemented;
    }
}

346
extern "C" Box* floatMulFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
347 348
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
349 350 351
    return boxFloat(lhs->d * rhs->d);
}

352
extern "C" Box* floatMulInt(BoxedFloat* lhs, BoxedInt* rhs) {
353 354 355
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxFloat(lhs->d * rhs->n);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
356 357
}

358
extern "C" Box* floatMul(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
359 360
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
361
        return floatMulInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
362
    } else if (rhs->cls == float_cls) {
363
        return floatMulFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
364 365 366 367 368
    } else {
        return NotImplemented;
    }
}

369
extern "C" Box* floatSubFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
370 371
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
372 373 374
    return boxFloat(lhs->d - rhs->d);
}

375
extern "C" Box* floatSubInt(BoxedFloat* lhs, BoxedInt* rhs) {
376 377 378
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxFloat(lhs->d - rhs->n);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
379 380
}

381
extern "C" Box* floatSub(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
382 383
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
384
        return floatSubInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
385
    } else if (rhs->cls == float_cls) {
386
        return floatSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
387 388 389 390 391
    } else {
        return NotImplemented;
    }
}

392
extern "C" Box* floatRSubFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
393 394 395 396 397
    assert(lhs->cls == float_cls);
    assert(rhs->cls == float_cls);
    return boxFloat(rhs->d - lhs->d);
}

398
extern "C" Box* floatRSubInt(BoxedFloat* lhs, BoxedInt* rhs) {
399 400 401 402 403
    assert(lhs->cls == float_cls);
    assert(rhs->cls == int_cls);
    return boxFloat(rhs->n - lhs->d);
}

404
extern "C" Box* floatRSub(BoxedFloat* lhs, Box* rhs) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
405 406
    assert(lhs->cls == float_cls);
    if (rhs->cls == int_cls) {
407
        return floatRSubInt(lhs, static_cast<BoxedInt*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
408
    } else if (rhs->cls == float_cls) {
409
        return floatRSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
410 411 412 413 414
    } else {
        return NotImplemented;
    }
}

415
Box* floatNeg(BoxedFloat* self) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
416 417 418 419
    assert(self->cls == float_cls);
    return boxFloat(-self->d);
}

420
bool floatNonzeroUnboxed(BoxedFloat* self) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
421
    assert(self->cls == float_cls);
422 423 424
    return self->d != 0.0;
}

425
Box* floatNonzero(BoxedFloat* self) {
426
    return boxBool(floatNonzeroUnboxed(self));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
}

std::string floatFmt(double x, int precision, char code) {
    char fmt[5] = "%.*g";
    fmt[3] = code;

    if (isnan(x)) {
        return "nan";
    }
    if (isinf(x)) {
        if (x > 0)
            return "inf";
        return "-inf";
    }

    char buf[40];
    int n = snprintf(buf, 40, fmt, precision, x);

    int dot = -1;
    int exp = -1;
    int first = -1;
    for (int i = 0; i < n; i++) {
        char c = buf[i];
        if (c == '.') {
            dot = i;
        } else if (c == 'e') {
            exp = i;
        } else if (first == -1 && c >= '0' && c <= '9') {
            first = i;
        }
    }

    if (dot == -1 && exp == -1) {
        if (n == precision) {
            memmove(buf + first + 2, buf + first + 1, (n - first - 1));
            buf[first + 1] = '.';
            exp = n + 1;
464
            int exp_digs = snprintf(buf + n + 1, 5, "e%+.02d", (n - first - 1));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
465 466 467 468
            n += exp_digs + 1;
            dot = 1;
        } else {
            buf[n] = '.';
469
            buf[n + 1] = '0';
Kevin Modzelewski's avatar
Kevin Modzelewski committed
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
            n += 2;

            return std::string(buf, n);
        }
    }

    if (exp != -1 && dot == -1) {
        return std::string(buf, n);
    }

    assert(dot != -1);

    int start, end;
    if (exp) {
        start = exp - 1;
        end = dot;
    } else {
        start = n - 1;
        end = dot + 2;
    }
    for (int i = start; i >= end; i--) {
        if (buf[i] == '0') {
            memmove(buf + i, buf + i + 1, n - i - 1);
            n--;
        } else if (buf[i] == '.') {
            memmove(buf + i, buf + i + 1, n - i - 1);
            n--;
            break;
        } else {
            break;
        }
    }
    return std::string(buf, n);
}

505
Box* floatNew1(BoxedClass* cls) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
506 507 508 509 510
    assert(cls == float_cls);
    // TODO intern this?
    return boxFloat(0.0);
}

511
Box* floatNew2(BoxedClass* cls, Box* a) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
512 513 514 515 516
    assert(cls == float_cls);

    if (a->cls == float_cls) {
        return a;
    } else if (a->cls == str_cls) {
517
        const std::string& s = static_cast<BoxedString*>(a)->s;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
518 519 520 521 522 523 524 525 526
        if (s == "nan")
            return boxFloat(NAN);
        if (s == "-nan")
            return boxFloat(-NAN);
        if (s == "inf")
            return boxFloat(INFINITY);
        if (s == "-inf")
            return boxFloat(-INFINITY);

527
        return boxFloat(strtod(s.c_str(), NULL));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
528 529 530 531
    }
    RELEASE_ASSERT(0, "%s", getTypeName(a)->c_str());
}

532
Box* floatStr(BoxedFloat* self) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
533 534 535 536
    assert(self->cls == float_cls);
    return boxString(floatFmt(self->d, 12, 'g'));
}

537
Box* floatRepr(BoxedFloat* self) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
538 539 540 541 542 543 544 545 546
    assert(self->cls == float_cls);
    return boxString(floatFmt(self->d, 16, 'g'));
}

extern "C" void printFloat(double d) {
    std::string s = floatFmt(d, 12, 'g');
    printf("%s", s.c_str());
}

547 548
static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* float_func, void* int_func,
                     void* boxed_func) {
549
    std::vector<ConcreteCompilerType*> v_ff, v_fi, v_fu;
550 551 552 553 554 555 556 557
    v_ff.push_back(BOXED_FLOAT);
    v_ff.push_back(BOXED_FLOAT);
    v_fi.push_back(BOXED_FLOAT);
    v_fi.push_back(BOXED_INT);
    v_fu.push_back(BOXED_FLOAT);
    v_fu.push_back(NULL);

    CLFunction* cl = createRTFunction();
558 559
    addRTFunction(cl, float_func, rtn_type, v_ff, false);
    addRTFunction(cl, int_func, rtn_type, v_fi, false);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
560 561 562 563 564 565 566
    addRTFunction(cl, boxed_func, NULL, v_fu, false);
    float_cls->giveAttr(name, new BoxedFunction(cl));
}

void setupFloat() {
    float_cls->giveAttr("__name__", boxStrConstant("float"));

567
    _addFunc("__add__", BOXED_FLOAT, (void*)floatAddFloat, (void*)floatAddInt, (void*)floatAdd);
568
    float_cls->giveAttr("__radd__", float_cls->getattr("__add__"));
569 570 571

    _addFunc("__div__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatDiv);
    _addFunc("__rdiv__", BOXED_FLOAT, (void*)floatRDivFloat, (void*)floatRDivInt, (void*)floatRDiv);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
572
    float_cls->giveAttr("__floordiv__", new BoxedFunction(boxRTFunction((void*)floatFloorDiv, NULL, 2, false)));
573 574 575 576 577 578 579 580 581 582 583

    _addFunc("__eq__", BOXED_BOOL, (void*)floatEqFloat, (void*)floatEqInt, (void*)floatEq);
    _addFunc("__ge__", BOXED_BOOL, (void*)floatGeFloat, (void*)floatGeInt, (void*)floatGe);
    _addFunc("__gt__", BOXED_BOOL, (void*)floatGtFloat, (void*)floatGtInt, (void*)floatGt);
    _addFunc("__le__", BOXED_BOOL, (void*)floatLeFloat, (void*)floatLeInt, (void*)floatLe);
    _addFunc("__lt__", BOXED_BOOL, (void*)floatLtFloat, (void*)floatLtInt, (void*)floatLt);
    _addFunc("__ne__", BOXED_BOOL, (void*)floatNeFloat, (void*)floatNeInt, (void*)floatNe);

    _addFunc("__mod__", BOXED_FLOAT, (void*)floatModFloat, (void*)floatModInt, (void*)floatMod);
    _addFunc("__rmod__", BOXED_FLOAT, (void*)floatRModFloat, (void*)floatRModInt, (void*)floatRMod);
    _addFunc("__mul__", BOXED_FLOAT, (void*)floatMulFloat, (void*)floatMulInt, (void*)floatMul);
584
    float_cls->giveAttr("__rmul__", float_cls->getattr("__mul__"));
585 586 587 588

    _addFunc("__pow__", BOXED_FLOAT, (void*)floatPowFloat, (void*)floatPowInt, (void*)floatPow);
    _addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
    _addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
589

590
    CLFunction* __new__ = boxRTFunction((void*)floatNew1, NULL, 1, false);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
591 592 593 594
    addRTFunction(__new__, (void*)floatNew2, NULL, 2, false);
    float_cls->giveAttr("__new__", new BoxedFunction(__new__));

    float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, NULL, 1, false)));
595
    CLFunction* nonzero = boxRTFunction((void*)floatNonzeroUnboxed, BOOL, 1, false);
596 597
    addRTFunction(nonzero, (void*)floatNonzero, UNKNOWN, 1, false);
    float_cls->giveAttr("__nonzero__", new BoxedFunction(nonzero));
598
    // float_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)floatNonzero, NULL, 1, false)));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
599 600 601 602 603 604 605 606
    float_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)floatStr, NULL, 1, false)));
    float_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)floatRepr, NULL, 1, false)));
    float_cls->freeze();
}

void teardownFloat() {
}
}