Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error On 32 bit architecture device (iPhone 5c,iPhone 4s) #29

Open
patelgaurav4u opened this issue Mar 22, 2018 · 8 comments
Open

Error On 32 bit architecture device (iPhone 5c,iPhone 4s) #29

patelgaurav4u opened this issue Mar 22, 2018 · 8 comments
Labels

Comments

@patelgaurav4u
Copy link

Integer literal '8000000000' overflows when stored into 'Int'

@Yaro812
Copy link

Yaro812 commented Apr 10, 2018

for those who installed this lib via CocoaPods and don't need support for older device there is the same error when archiving.
To avoid this error one can add following to the end of Podfile
post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['ARCHS'] = 'arm64' end end end

@scgyong
Copy link

scgyong commented Sep 6, 2018

I was using version 2.0, and I had problems with 32bit architecture devices.
After updating recent version, I got this 8000000000 literal error. But I had to support these devices. So I went back to version 2.0.
Problem was somehow (I don't know why) UInt64.multipliedFullWidth(by: r) doesn't work properly and produced this runtime error: Thread 1: Fatal error: Operation is not supported
So I wrote my own multipliedFullWidth function using 32-bit operation:

public func multiplyFullWidth(_ ab: UInt64, _ cd: UInt64) -> (hi: UInt64, lo: UInt64) {
    let a: UInt32 = UInt32(ab >> 32)
    let b: UInt32 = UInt32(ab & 0xFFFFFFFF)
    let c: UInt32 = UInt32(cd >> 32)
    let d: UInt32 = UInt32(cd & 0xFFFFFFFF)
    let (ach, acl) = a.multipliedFullWidth(by: c)
    let (adh, adl) = a.multipliedFullWidth(by: d)
    let (bch, bcl) = b.multipliedFullWidth(by: c)
    let (bdh, bdl) = b.multipliedFullWidth(by: d)
    
    var lo: UInt64 = UInt64(bdh) << 32 + UInt64(bdl)
    var hi: UInt64 = UInt64(ach) << 32 + UInt64(acl) + UInt64(adh) + UInt64(bch)
    
    var overflow = false
    (lo, overflow) = lo.addingReportingOverflow(UInt64(adl) << 32)
    if overflow { hi += 1 }
    (lo, overflow) = lo.addingReportingOverflow(UInt64(bcl) << 32)
    if overflow { hi += 1 }

    return (hi, lo)
}

and modified code like

                    (mulHi, mulLo) = l.multipliedFullWidth(by: r)

into

                if (MemoryLayout<Int>.size == MemoryLayout<Int32>.size) {
                    //print("32-bit architecture")
                    (mulHi, mulLo) = multiplyFullWidth(l, r)
                } else {
                    //print("64-bit architecture")
                    (mulHi, mulLo) = l.multipliedFullWidth(by: r)
                }

There were three multiplyFullWidth() calls in the code, So I replaced them all, and now it works fine.

As far as I know, iOS 11 started to exclude 32-bit devices. But those devices are still working, and developers should consider supporting them. Devices running on iOS8 still exist, and many apps are targetting those old iOSs.

So can you support those devices? You can use the above codes. Honestly I did not see the recent version change, but I believe you can support them modifying some little code.

I hope this can help.

@twodayslate
Copy link
Collaborator

twodayslate commented Sep 6, 2018

@scgyong Submit a PR and I'll merge it.

Instead of changing every instance of

 (mulHi, mulLo) = l.multipliedFullWidth(by: r)

You could have the architecture check inside of multipliedFullWidth

func multipliedFullWidthDigit(by multiplicand: Digit) -> (Digit, Digit)
{
    if (MemoryLayout<Int>.size == MemoryLayout<Int32>.size) {
        let a: UInt32 = UInt32(self >> 32)
        let b: UInt32 = UInt32(self & 0xFFFFFFFF)
        let c: UInt32 = UInt32(multiplicand >> 32)
        let d: UInt32 = UInt32(multiplicand & 0xFFFFFFFF)
        let (ach, acl) = a.multipliedFullWidth(by: c)
        let (adh, adl) = a.multipliedFullWidth(by: d)
        let (bch, bcl) = b.multipliedFullWidth(by: c)
        let (bdh, bdl) = b.multipliedFullWidth(by: d)
        
        var lo: UInt64 = UInt64(bdh) << 32 + UInt64(bdl)
        var hi: UInt64 = UInt64(ach) << 32 + UInt64(acl) + UInt64(adh) + UInt64(bch)
        
        var overflow = false
        (lo, overflow) = lo.addingReportingOverflow(UInt64(adl) << 32)
        if overflow { hi += 1 }
        (lo, overflow) = lo.addingReportingOverflow(UInt64(bcl) << 32)
        if overflow { hi += 1 }

        return (hi, lo)
    }

    let (lLo, lHi) = (self % DigitHalfBase, self / DigitHalfBase)
    let (rLo, rHi) = (multiplicand % DigitHalfBase, multiplicand / DigitHalfBase)

    let K = (lHi * rLo) + (rHi * lLo)

    var resLo = (lLo * rLo) + ((K % DigitHalfBase) * DigitHalfBase)
    var resHi = (lHi * rHi) + (K / DigitHalfBase)

    if resLo >= DigitBase
    {
        resLo -= DigitBase
        resHi += 1
    }

    return (resLo, resHi)
}

No?

(above method untested)

@twodayslate twodayslate added the bug label Sep 6, 2018
@scgyong
Copy link

scgyong commented Sep 6, 2018

Honestly I didn't try to understand the codes like Limb and Digit. I just recognized those are aliased to UInt64.

And multipliedFullWidthDigit(by:) is defined in the extension of Digit, but the code I modified is for UInt64.multipliedFullWidth(by:) defined in Swift > Math > Integers. I'm not sure your code above would work.

According to your suggestion, architecture check can be done in my function multiplyFullWidth(). But I think If a developer doesn't want to support 32-bit architecture devices, he/she also would not want to check the int length at runtime.

So, It would be great if there is compile-time check if the target is for 32-bit, and if it's true, runtime check should be done. And, what is the cost of MemoryLayout<Int>.size == MemoryLayout<Int32>.size? Is it ignorable or should be checked once at startup?

Additionally, I don't know how 8_000_000_000 literal thing (and others if exist) can be modified for 32-bit architecture.

I think I know too little to submit some code. Can you please do that?

@twodayslate
Copy link
Collaborator

I'll look at it in more detail and if I submit a PR I'll tag you in it.

@scgyong
Copy link

scgyong commented Sep 6, 2018

@twodayslate thanks a lot

@kwgithubusername
Copy link

Hi, is there any progress on this? A small fraction of our users aren’t able to create XLM accounts because of this issue.

@twodayslate
Copy link
Collaborator

twodayslate commented Nov 8, 2018

@woudini I haven't started. Feel free to submit a PR

edit:// I probably won't be working on this - getting harder to test 32bit stuff since everything is 64... any tips to properly test are welcomed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants